当前位置: 首页 > news >正文

微软(TTS)文本转语音服务API实现

此博客实现与java实现微软文本转语音(TTS)经验总结_java tts_${简简单单}的博客-CSDN博客之上,首先感谢博客源码的提供,本人在上面添加了一些详细的注释,方便大家跟好的理解和使用,毕竟我已经用原文调试了一下午才调通,一些细节的问题给大家标注出来,免得浪费大家的时间,下面直接开始代码吧!

首先大家需要去微软官网获取到密钥,方便调用时可以使用,大家注意看下图,我们一定要注意给我们分配到的区域,我这里是分配到eastus ,就是east us(美国东部)的意思,大家一定需要注意一下,后面会使用到的,然后终结点里面的地址就是我们获取token的地址

下面我们准备几个类,方便后面使用,大家把代码都复制到自己项目中,不要有遗漏:

package com.daoversal.util;public class ByteArray {private byte[] data;private int length;public ByteArray(){length = 0;data = new byte[length];}public ByteArray(byte[] ba){data = ba;length = ba.length;}/**合并数组*/public  void cat(byte[] second, int offset, int length){if(this.length + length > data.length) {int allocatedLength = Math.max(data.length, length);byte[] allocated = new byte[allocatedLength << 1];System.arraycopy(data, 0, allocated, 0, this.length);System.arraycopy(second, offset, allocated, this.length, length);data = allocated;}else {System.arraycopy(second, offset, data, this.length, length);}this.length += length;}public  void cat(byte[] second){cat(second, 0, second.length);}public byte[] getArray(){if(length == data.length){return data;}byte[] ba = new byte[length];System.arraycopy(data, 0, ba, 0, this.length);data = ba;return ba;}public int getLength(){return length;}
}
package com.daoversal.util;import javax.net.ssl.HttpsURLConnection;
import java.net.URL;public class HttpsConnection {public static HttpsURLConnection getHttpsConnection(String connectingUrl) throws Exception {URL url = new URL(connectingUrl);return (HttpsURLConnection) url.openConnection();}
}
package com.daoversal.util;import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;@Slf4j
public class XmlDom {public static String createDom(String locale, String genderName, String voiceName, String textToSynthesize){Document doc = null;Element speak, voice;try {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dbf.newDocumentBuilder();doc = builder.newDocument();if (doc != null){speak = doc.createElement("speak");speak.setAttribute("version", "1.0");speak.setAttribute("xml:lang", "en-US");voice = doc.createElement("voice");voice.setAttribute("xml:lang", locale);voice.setAttribute("xml:gender", genderName);voice.setAttribute("name", voiceName);voice.appendChild(doc.createTextNode(textToSynthesize));speak.appendChild(voice);doc.appendChild(speak);}} catch (ParserConfigurationException e) {log.error("Create ssml document failed: {}",e.getMessage());return null;}return transformDom(doc);}private static String transformDom(Document doc){StringWriter writer = new StringWriter();try {TransformerFactory tf = TransformerFactory.newInstance();Transformer transformer;transformer = tf.newTransformer();transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");transformer.transform(new DOMSource(doc), new StreamResult(writer));} catch (TransformerException e) {log.error("Transform ssml document failed: {}",e.getMessage());return null;}return writer.getBuffer().toString().replaceAll("\n|\r", "");}
}

 下面这个类我给大家重点讲一下,大家去下面网址看看自己的参数Text to speech API reference (REST) - Speech service - Azure AI services | Microsoft Learn

AUDIO_24KHZ_48KBITRATE_MONO_MP3 :语言类型,这个不重要,那个声音好听用那个,去下图找:

ACCESS_TOKEN_URI :就是本文章的第一张图里面,里面获取token的地址,直接将地址复制进来就好了。

API_KEY :自己的api key,就是密钥。

 TTS_SERVICE_URI : 这个地址一定要对应分配的区域才行,不然会报权限错误

Synthesis tts speech failed Server returned HTTP response code: 401 for URL: https://.........

我这里是 east us(美国东部),所以就使用美国东部里面的地址即可。

package com.daoversal.util;public class TtsConst {/*** 音频合成类型(亲测这种效果最佳,其他的你自己去试试)* 里面有很多类型,可以去里面找自己需要的* https://learn.microsoft.com/en-us/azure/ai-services/speech-service/rest-text-to-speech?tabs=streaming*/public static final String AUDIO_24KHZ_48KBITRATE_MONO_MP3 = "audio-24khz-48kbitrate-mono-mp3";/*** 授权url   获取密钥页面 终结点 里面的地址,我们使用这个获取token*/public static final String ACCESS_TOKEN_URI = "token获取地址";/*** api key*/public static final String API_KEY = "自己的密钥";/*** tts服务url,这里一定要根据自己分配的地区找相应的地址才行*/public static final String TTS_SERVICE_URI = "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1/";}

下面参数给大家讲一下:

textToSynthesize : 传入的合成语音文本内容

locale:语言类型,大家可以参考,中文在嵌入式语音里面,大家可以在两个页面找到自己需要的语言。

Embedded Speech - Speech service - Azure AI services | Microsoft Learn

Language support - Speech service - Azure AI services | Microsoft Learn

gender:为发声人性别,Male表示男性

 voiceName :发声者名称,大家可以去下图找出对应的,比如中文的话:

package com.daoversal.util;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import java.io.DataOutputStream;
import java.io.InputStream;@Slf4j
@Component
public class TtsService {@Resourceprivate Authentication authentication;/*** 合成音频* @param textToSynthesize 传入需要翻译的文本* @param locale    要合成的语言类型* @param gender    性别* @param voiceName 发音者名称* @return*/public byte[] genAudioBytes(String textToSynthesize, String locale, String gender, String voiceName) {String accessToken = authentication.genAccessToken();if (StringUtils.isEmpty(accessToken)) {return new byte[0];}try {HttpsURLConnection webRequest = HttpsConnection.getHttpsConnection(TtsConst.TTS_SERVICE_URI);webRequest.setRequestProperty("Host", "eastus.tts.speech.microsoft.com");webRequest.setRequestProperty("Content-Type", "application/ssml+xml");webRequest.setRequestProperty("X-Microsoft-OutputFormat", TtsConst.AUDIO_24KHZ_48KBITRATE_MONO_MP3);webRequest.setRequestProperty("Authorization", "Bearer " + accessToken);webRequest.setRequestProperty("Ocp-Apim-Subscription-Key", TtsConst.API_KEY);webRequest.setRequestProperty("User-Agent", "Mozilla/5.0");webRequest.setRequestProperty("Accept", "*/*");webRequest.setDoInput(true);webRequest.setDoOutput(true);webRequest.setConnectTimeout(5000);webRequest.setReadTimeout(300000);webRequest.setRequestMethod("POST");String body = XmlDom.createDom(locale, gender, voiceName, textToSynthesize);if (StringUtils.isEmpty(body)) {return new byte[0];}byte[] bytes = body.getBytes();webRequest.setRequestProperty("content-length", String.valueOf(bytes.length));webRequest.connect();DataOutputStream dop = new DataOutputStream(webRequest.getOutputStream());dop.write(bytes);dop.flush();dop.close();InputStream inSt = webRequest.getInputStream();ByteArray ba = new ByteArray();int rn2 = 0;int bufferLength = 4096;byte[] buf2 = new byte[bufferLength];while ((rn2 = inSt.read(buf2, 0, bufferLength)) > 0) {ba.cat(buf2, 0, rn2);}inSt.close();webRequest.disconnect();return ba.getArray();} catch (Exception e) {log.error("Synthesis tts speech failed {}", e.getMessage());}return null;}}

最后就是调用了,大家可以测试了:

package com.daoversal.web;import com.daoversal.framework.http.Response;
import com.daoversal.task.DvWeekCountTask;
import com.daoversal.task.RechargeTask;
import com.daoversal.task.UserGradeCountTask;
import com.daoversal.task.WindControlMsgTask;
import com.daoversal.util.TtsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import okhttp3.*;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;/*** <p>* 套餐价值释放记录表 前端控制器* </p>** @author HayDen* @since 03 22 10:44:13*/
@RestController
@RequestMapping("/test")
@Api(value = "test")
public class TestController {@Resourceprivate TtsService testService;@PostMapping("/ttsService")@ApiOperation(value = "获取ttsService", httpMethod = "POST" )public void ttsService(String text) {// byte[] bte = testService.genAudioBytes(res,"en-US","Male","en-US-JennyNeural");byte[] bte = testService.genAudioBytes(text,"zh-CN","Male","zh-CN-YunxiNeural");String value = "hllo.mp3";convertByteArrayToFile(bte,value);System.out.println("213213123");}/*** 此文件是将byte[] 转换成文件存储到指定路径的* @param arr* @param value*/public static void convertByteArrayToFile(byte[] arr,String value) {try (BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(arr));//这里是转换以后的文件存储的路径FileOutputStream fileOutputStream = new FileOutputStream("/Users/recovery/Downloads/"+value);BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream)) {int data;while ((data = bis.read()) != -1) {bos.write(data);}bos.flush();} catch (IOException e) {e.printStackTrace();}}}

最后大家需要注意一下就是如果你选的是英文en-US,但是输入的文本是中文的话他是不会翻译的,所以大家一定要注意自己的语言类型不要弄错了,如果有疑问可以留言哦,我看到肯定会毫无保留的给大家说明的。

​​​​​​​

相关文章:

微软(TTS)文本转语音服务API实现

此博客实现与java实现微软文本转语音&#xff08;TTS&#xff09;经验总结_java tts_${简简单单}的博客-CSDN博客之上&#xff0c;首先感谢博客源码的提供&#xff0c;本人在上面添加了一些详细的注释&#xff0c;方便大家跟好的理解和使用&#xff0c;毕竟我已经用原文调试了一…...

防火墙firewalld

title: 防火墙firewalld createTime: 2020-10-29 18:05:52 updateTime: 2020-10-29 18:05:52 categories: linux tags: centos7上的firewalld 的使用 一、firewalld的基本启动关闭命令 启动服务------systemctl start firewalld关闭服务------systemctl stop firewalld查看状…...

SW线光源是真实的(点光源)

点光源在渲染下真实 点光源地板反射是对的...

Vue Router的安装

安装 在我们使用脚手架搭建项目的时候&#xff0c;默认是没有帮我们安装的。需要自己手动进行安装。安装的 Vue-Router 插件时需要注意版本信息&#xff0c;Vue2.0 使用的是 Vue-Router3.x &#xff0c;而 Vue3.0 使用的是 Vue-Router4.x。 通过命令安装 vue-router3 插件 $…...

ROS架构设计

ROS架构如图所示&#xff0c;可以将其分为三个层次&#xff1a;OS层、中间层和应用层。 1.OS层 ROS并不是一个传统意义上的操作系统&#xff0c;无法像Windows、Linux一样直接运行在计算机硬件之上&#xff0c;而是需要依托于Linux系统。所以在OS层&#xff0c;我们可以直接使…...

JSON.toJSONString() 解析之后 出现“$ref“:“$[x].xxx“

原因&#xff1a;JSON在处理数据时出现了相同数据&#xff0c;JSON自动将相同节点的数据使用引用方式代替。 解决方式&#xff1a; String jsonString JSON.toJSONString(params, SerializerFeature.DisableCircularReferenceDetect); SerializerFeature.DisableCircularRefer…...

2023研究生数学建模E题思路+模型+代码+论文(持续更新中) 出血性脑卒中临床智能诊疗建模

目录 E题思路 出血性脑卒中临床智能诊疗建模 完整思路代码模型论文获取见文末名片 完整思路代码模型论文获取见此 E题思路 出血性脑卒中临床智能诊疗建模 完整思路代码模型论文获取见文末名片 一、 背景介绍 出血性脑卒中指非外伤性脑实质内血管破裂引起的脑出血&#xff0…...

云可观测性安全平台——掌动智能

云可观测性安全平台是一个跨架构、跨平台的可观测性方案&#xff0c;实现对云环境下的细粒度数据可视化&#xff0c;满足安全部门对云内部安全领域的多场景诉求&#xff0c;包括敏感数据动态监管、云网攻击回溯分析、攻击横移风险监控、云异常流量分析。本文将介绍掌动智能云可…...

[ruby on rails] postgres sql explain 优化

一、查看执行计划 sql User.all.to_sql # 不会实际执行查询 puts ActiveRecord::Base.connection.explain(sql)# 会实际执行查询&#xff0c;再列出计划 User.all.explain# 会实际执行查询&#xff0c;再列出计划ActiveRecord::Base.connection.execute(EXPLAIN ANALYZE sql…...

YOLOv7改进:GAMAttention注意力机制

1.背景介绍 为了提高各种计算机视觉任务的性能&#xff0c;人们研究了各种注意机制。然而&#xff0c;以往的方法忽略了保留通道和空间方面的信息以增强跨维度交互的重要性。因此&#xff0c;我们提出了一种全局调度机制&#xff0c;通过减少信息缩减和放大全局交互表示来提高深…...

83、SpringBoot --- 下载和安装 MSYS2、 Redis

启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe redis.windows.conf 启动redis客户端&#xff1a; 小黑窗&#xff1a;redis-cli …...

用css画一个半圆弧(以小程序为例)

一、html结构 圆弧的html结构是 两个块级元素嵌套。 <View classNamewrap><View className"inner">{/* 图标下的内容 */}</View></View>二、css样式&#xff1a;原理是两个半圆叠在一起&#xff0c;就是一个半圆弧。那么&#xff0c;如何画一…...

redis介绍

一、简介 Redis 与其他 key - value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保存在磁盘中&#xff0c;重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据&#xff0c;同时还提供list&#xff0c;…...

数学建模常用模型

作为数学建模的编程手还掌握一些各类模型常用算法&#xff0c;数学建模评价类模型、分类模型、预测类模型比较常用的方法总结如下&#xff1a; 接下来对这些比较典型的模型进行详细进行介绍说明。 一、评价模型 在数学建模中&#xff0c;评价模型是比较基础的模型之一&#x…...

Linux 基本语句_5_创建静态库|动态库

静态库 创建主函数&#xff1a;main.c 应用函数&#xff1a;add.c、sub.c、mul.c 创建calc.h文件作为头文件 生成可执行文件*.o文件 gcc -c add.c -o add.o ....包装*.o文件为静态库 ar -rc libmymath.a add.o sub.o mul.o编译静态库并指明创建静态库的位置 sudo gcc mai…...

【每日一题】2703. 返回传递的参数的长度

2703. 返回传递的参数的长度 - 力扣&#xff08;LeetCode&#xff09; 请你编写一个函数 argumentsLength&#xff0c;返回传递给该函数的参数数量。 示例 1&#xff1a; 输入&#xff1a;args [5] 输出&#xff1a;1 解释&#xff1a; argumentsLength(5); // 1只传递了一个值…...

虚拟DOM详解

面试题&#xff1a;请你阐述一下对vue虚拟dom的理解 什么是虚拟dom&#xff1f; 虚拟dom本质上就是一个普通的JS对象&#xff0c;用于描述视图的界面结构 在vue中&#xff0c;每个组件都有一个render函数&#xff0c;每个render函数都会返回一个虚拟dom树&#xff0c;这也就意味…...

Linux配置命令

一&#xff1a;HCSA-VM-Linux安装虚拟机后的基础命令 1.代码命令 1.查看本机IP地址&#xff1a; ip addr 或者 ip a [foxbogon ~]$ ip addre [foxbogon ~]$ ip a 1&#xff1a;<Loopback,U,LOWER-UP> 为环回2网卡 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP&g…...

Kafka:介绍和内部工作原理

展示Kafka工作方式的简单架构。 什么是Kafka&#xff1f;为什么我们要使用它&#xff1f;它是消息队列吗&#xff1f; 它是一个分布式流处理平台或分布式提交日志。 Kafka通常用于实时流数据管道&#xff0c;即在系统之间传输数据&#xff0c;构建不断流动的数据转换系统和构…...

在 EMR Serverless 上使用 Delta Lake

本文是一份开箱即用的全自动测试脚本&#xff0c;用于在 EMR Serverless 上提交一个 Delta Lake 作业。本文完全遵循《最佳实践&#xff1a;如何优雅地提交一个 Amazon EMR Serverless 作业&#xff1f;》 一文给出的标准和规范&#xff01; 1. 导出环境相关变量 注意&#x…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...