Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理
Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理
目录
Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理
一、简单介绍
二、实现原理
三、注意事项
四、实现步骤
五、关键代码
一、简单介绍
Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。
本节介绍,这里在使用微软的Azure 使用SSML进行SS语音合成的音频,并且获取表情嘴型Animation 数据,并且保存到本地,在特定的情况下,用于本地读取音频和表情嘴型Animation 数据,直接使用,避免可能网络访问造成的延迟问题,这里简单说明,如果你有更好的方法,欢迎留言交流。
语音合成标记语言 (SSML) 是一种基于 XML 的标记语言,可用于微调文本转语音输出属性,例如音调、发音、语速、音量等。 与纯文本输入相比,你拥有更大的控制权和灵活性。
可以使用 SSML 来执行以下操作:
- 定义输入文本结构,用于确定文本转语音输出的结构、内容和其他特征。 例如,可以使用 SSML 来定义段落、句子、中断/暂停或静音。 可以使用事件标记(例如书签或视素)来包装文本,这些标记可以稍后由应用程序处理。
- 选择语音、语言、名称、样式和角色。 可以在单个 SSML 文档中使用多个语音。 调整重音、语速、音调和音量。 还可以使用 SSML 插入预先录制的音频,例如音效或音符。
- 控制输出音频的发音。 例如,可以将 SSML 与音素和自定义词典配合使用来改进发音。 还可以使用 SSML 定义单词或数学表达式的具体发音。
下面是 SSML 文档的基本结构和语法的子集:
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="string"><mstts:backgroundaudio src="string" volume="string" fadein="string" fadeout="string"/><voice name="string" effect="string"><audio src="string"></audio><bookmark mark="string"/><break strength="string" time="string" /><emphasis level="value"></emphasis><lang xml:lang="string"></lang><lexicon uri="string"/><math xmlns="http://www.w3.org/1998/Math/MathML"></math><mstts:audioduration value="string"/><mstts:express-as style="string" styledegree="value" role="string"></mstts:express-as><mstts:silence type="string" value="string"/><mstts:viseme type="string"/><p></p><phoneme alphabet="string" ph="string"></phoneme><prosody pitch="value" contour="value" range="value" rate="value" volume="value"></prosody><s></s><say-as interpret-as="string" format="string" detail="string"></say-as><sub alias="string"></sub></voice> </speak>
SSML 语音和声音
语音合成标记语言 (SSML) 的语音和声音 - 语音服务 - Azure AI services | Microsoft Learn
官网注册:
面向学生的 Azure - 免费帐户额度 | Microsoft Azure
官网技术文档网址:
技术文档 | Microsoft Learn
官网的TTS:
文本转语音快速入门 - 语音服务 - Azure Cognitive Services | Microsoft Learn
Azure Unity SDK 包官网:
安装语音 SDK - Azure Cognitive Services | Microsoft Learn
SDK具体链接:
https://aka.ms/csspeech/unitypackage

二、实现原理
1、官网申请得到语音合成对应的 SPEECH_KEY 和 SPEECH_REGION
2、然后对应设置 语言 和需要的声音 配置
3、使用 SSML 带有流式获取得到音频数据,在声源中播放或者保存即可,样例如下
public static async Task SynthesizeAudioAsync()
{var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);var ssml = File.ReadAllText("./ssml.xml");var result = await speechSynthesizer.SpeakSsmlAsync(ssml);using var stream = AudioDataStream.FromResult(result);await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}
4、本地保存音频,以及表情嘴型 Animation 数据
// 获取到视频的数据,保存为 .wav using var stream = AudioDataStream.FromResult(speechSynthesisResult);await stream.SaveToWaveFileAsync($"./{fileName}.wav");/// <summary>/// 嘴型 animation 数据,本地保存为 json 数据/// </summary>/// <param name="fileName">保存文件名</param>/// <param name="content">保存内容</param>/// <returns></returns>static async Task CommitAsync(string fileName,string content){var bits = Encoding.UTF8.GetBytes(content);using (var fs = new FileStream(path: @$"d:\temp\{fileName}.json",mode: FileMode.Create,access: FileAccess.Write,share: FileShare.None,bufferSize: 4096,useAsync: true)){await fs.WriteAsync(bits, 0, bits.Length);}}
三、注意事项
1、不是所有的 speechSynthesisVoiceName 都能生成对应的 表情嘴型 Animation 数据
四、实现步骤
这里是直接使用 .Net VS 中进行代码测试
1、在 NuGet 中安装 微软的 Speech 包


2、代码编写实现 SSML 合成语音,并且本地保存对应的 音频文件和表情嘴型 Animation json 数据

3、运行代码,运行完后,就会本地保存对应的 音频文件和表情嘴型 Animation json 数据


4、本地查看保存的数据


五、关键代码
using Microsoft.CognitiveServices.Speech;
using System.Text;class Program
{// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"static string speechKey = "YOUR_SPEECH_KEY";static string speechRegion = "YOUR_SPEECH_REGION";static string speechSynthesisVoiceName = "zh-CN-XiaoxiaoNeural";static string fileName = "Test" + "Hello";static string InputAudioContent = "黄河之水天上来,奔流到海不复回"; // 生成的static int index = 0; // 记录合成的表情口型动画的数据数组个数static string content="["; // [ 是为了组成 json 数组async static Task Main(string[] args){var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);// 根据需要可以使用更多 xml 配置,让合成的声音更加生动立体var ssml = @$"<speak version='1.0' xml:lang='zh-CN' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'><voice name='{speechSynthesisVoiceName}'><mstts:viseme type='FacialExpression'/><mstts:express-as style='friendly'>{InputAudioContent}</mstts:express-as></voice></speak>";// Required for sentence-level WordBoundary eventsspeechConfig.SetProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");using (var speechSynthesizer = new SpeechSynthesizer(speechConfig)){// Subscribe to events// 注册表情嘴型数据speechSynthesizer.VisemeReceived += async (s, e) =>{Console.WriteLine($"VisemeReceived event:" +$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" + $"\r\n\tVisemeId: {e.VisemeId}" // + $"\r\n\tAnimation: {e.Animation}");if (string.IsNullOrEmpty( e.Animation)==false){// \r\n, 是为了组合 json 格式content += e.Animation + "\r\n,";index++;}};// 注册合成完毕的事件speechSynthesizer.SynthesisCompleted += async (s, e) =>{Console.WriteLine($"SynthesisCompleted event:" +$"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +$"\r\n\tindex: {index} " +$"\r\n\tAudioDuration: {e.Result.AudioDuration}");content = content.Substring(0, content.Length-1);content += "]";await CommitAsync(fileName, content);};// Synthesize the SSMLConsole.WriteLine($"SSML to synthesize: \r\n{ssml}");var speechSynthesisResult = await speechSynthesizer.SpeakSsmlAsync(ssml);// 获取到视频的数据,保存为 .wav using var stream = AudioDataStream.FromResult(speechSynthesisResult);await stream.SaveToWaveFileAsync(@$"d:\temp\{fileName}.wav");// Output the resultsswitch (speechSynthesisResult.Reason){case ResultReason.SynthesizingAudioCompleted:Console.WriteLine("SynthesizingAudioCompleted result");break;case ResultReason.Canceled:var cancellation = SpeechSynthesisCancellationDetails.FromResult(speechSynthesisResult);Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");if (cancellation.Reason == CancellationReason.Error){Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");}break;default:break;}}Console.WriteLine("Press any key to exit...");Console.ReadKey();}/// <summary>/// 嘴型 animation 数据,本地保存为 json 数据/// </summary>/// <param name="fileName">保存文件名</param>/// <param name="content">保存内容</param>/// <returns></returns>static async Task CommitAsync(string fileName,string content){var bits = Encoding.UTF8.GetBytes(content);using (var fs = new FileStream(path: @$"d:\temp\{fileName}.json",mode: FileMode.Create,access: FileAccess.Write,share: FileShare.None,bufferSize: 4096,useAsync: true)){await fs.WriteAsync(bits, 0, bits.Length);}}
}
相关文章:
Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理
Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理 目录 Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理 一、简单介绍 二、实现原理 三、注意事项 四、实现步骤 五、关键代码 一、简…...
安全学习DAY16_信息打点-CDN绕过
信息打点-CDN绕过 文章目录 信息打点-CDN绕过本节思维导图相关链接&工具站&项目工具前置知识:CDN配置:配置1:加速域名-需要启用加速的域名配置2:加速区域-需要启用加速的地区配置3:加速类型-需要启用加速的资源…...
genism word2vec方法
文章目录 概述使用示例模型的保存与使用训练参数详解([原链接](https://blog.csdn.net/weixin_44852067/article/details/130221655))语料库训练 概述 word2vec是按句子来处理的Sentences(句子们) 使用示例 from gensim.models import Word2Vec #sent…...
vue3自定义样式-路由-axios拦截器
基于vue,vite和elementPlus 基于elementPlus自定义样式 history模式的路由 在根目录配置jsconfig.json,添加json的配置项。输入自动联想到src目录,是根路径的别名拦截器 如果存在多个接口地址,可以配置多个axios实例 数据持久化之后&#x…...
【mysql】事务的四种特性的理解
🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风…...
C++中List的实现
前言 数据结构中,我们了解到了链表,但是我们使用时需要自己去实现链表才能用,但是C出现了list将这一切皆变为现。list可以看作是一个带头双向循环的链表结构,并且可以在任意的正确范围内进行增删查改数据的容器。list容器一样也是…...
ElementUI 树形表格的使用以及表单嵌套树形表格的校验问题等汇总
目录 一、树形表格如何添加序号体现层级关系 二、树形表格展开收缩图标位置放置,设置指定列 三、表单嵌套树形表格的校验问题以及如何给校验rules传参 普通表格绑定如下:这种方法只能校验表格的第一层,树形需要递归设置子级节点prop。 树…...
解决“Unable to start embedded Tomcat“错误的完整指南
系列文章目录 文章目录 系列文章目录前言一、查看错误信息二、确认端口是否被占用三、检查依赖版本兼容性四、清理临时文件夹五、检查应用程序配置六、检查依赖冲突七、查看异常堆栈信息八、升级或降级Spring Boot版本总结前言 在使用Spring Boot开发应用程序时,有时可能会遇…...
JVS开源基础框架:平台基本信息介绍
JVS是面向软件开发团队可以快速实现应用的基础开发脚手架,主要定位于企业信息化通用底座,采用微服务分布式框架,提供丰富的基础功能,集成众多业务引擎,它灵活性强,界面化配置对开发者友好,底层容…...
C++ - max_element
在C中,要找到一个数组中的最大元素,可以使用 std::max_element 函数。以下是使用步骤: 包含 <algorithm> 头文件,这里定义了 std::max_element 函数。声明一个数组,并初始化它。使用 std::max_element 函数来查找…...
聚隆转债上市价格预测
聚隆转债 基本信息 转债名称:聚隆转债,评级:A,发行规模:2.185亿元。 正股名称:南京聚隆,今日收盘价:16.64元,转股价格:18.27元。 当前转股价值 转债面值 / 转…...
pytest自动生成测试类 demo
一、 pytest自动生成测试类 demo # -*- coding:utf-8 -*- # Author: 喵酱 # time: 2023 - 08 -15 # File: test4.py # desc: import pytest import unittest# 动态生成测试类def create_test_class(class_name:str, test_cases:list) -> type:"""生成测试类…...
服务器卡顿了该如何处理
服务器卡顿了该如何处理 当Windows系统的服务器出现卡顿问题时,以下是一些常见的故障排除步骤: 1.检查网络连接:确保服务器的网络连接正常。检查网络设备、交换机、防火墙等设备,确保它们正常运行。尝试通过其他计算机访问服务器…...
常量对象 只能调用 常成员函数
一、遇到问题: //函数声明 void ReadRanFile(CString szFilePath); const CFvArray<CString>& GetPanelGrade() const { return m_fvArrayPanelGrade; } //在另一个文件中调用ReadtRanFile这个函数 const CFsJudConfig& psJudConfig m_pFsDefJu…...
Progressive-Hint Prompting Improves Reasoning in Large Language Models
本文是LLM系列的文章,针对《Progressive-Hint Prompting Improves Reasoning in Large Language Models》的翻译。 渐进提示改进了大型语言模型中的推理 摘要1 引言2 相关工作3 渐进提示Prompting4 实验5 结论6 实现细节7 不足与未来工作8 广泛的影响9 具有不同提示…...
mysql中INSERT INTO ... ON DUPLICATE KEY UPDATE的用法,以及与REPLACE INTO 语句用法的异同
INSERT INTO ... ON DUPLICATE KEY UPDATE 是 MySQL 中一种用于插入数据并处理重复键冲突的语法。与之相似的还有 REPLACE INTO 语句。以下是它们的用法和异同点的详细说明: 一、INSERT INTO ... ON DUPLICATE KEY UPDATE INSERT INTO ... ON DUPLICATE KEY UPDAT…...
wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容)
wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 1. 关键字 “与”:“eq” 和 “”等同,可以使用 “and” 表示并且, “或”:“or”表示或者。 “非”:“!" 和 "not”…...
MATLAB图形窗口固定
起因是上次作图的时候写了: clc clear close all 这三个典型的刷新语句 清空工作区、命令行并且关闭图窗 就导致每次我把图窗拉到合适的位置观察,再一次点击运行都会重新刷新在出生点(x) 所以想把图窗固定在某个位置 显然更…...
【数据结构】_7.二叉树概念与基本操作
目录 1.树形结构 1.1 树的概念 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的应用—表示文件系统的目录树结构 编辑2.二叉树 2.1 概念 2.2 特殊二叉树 2.3 二叉树的性质 2.4 二叉树的存储结构 2.4.1 顺序存储结构(数组存储结构) 2.4.2…...
Flink之Partitioner(分区规则)
Flink之Partitioner(分区规则) 方法注释global()全部发往1个taskbroadcast()广播(前面的文章讲解过,这里不做阐述)forward()上下游并行度一致时一对一发送,和同一个算子连中算子的OneToOne是一回事shuffle()随机分配(只是随机,同Spark的shuffle不同)rebalance()轮询分配,默认机…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
