当前位置:   article > 正文

Unity 工具 之 Azure 微软语音合成普通方式和流式获取音频数据的简单整理_unity音频流式传输

unity音频流式传输

Unity 工具 之 Azure 微软语音合成普通方式和流式获取音频数据的简单整理

目录

Unity 工具 之 Azure 微软语音合成普通方式和流式获取音频数据的简单整理

一、简单介绍

二、实现原理

三、注意实现

四、实现步骤

 六、关键脚本

附加:

声音设置相关


一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

本节介绍,这里在使用微软的Azure 进行语音合成的两个方法的做简单整理,这里简单说明,如果你有更好的方法,欢迎留言交流。

官网注册:

面向学生的 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、使用 普通方式 和 流式获取得到音频数据,在声源中播放即可

三、注意实现

1、在合成语音文本较长的情况下,流式获取的速度明显会优于普通的方式

2、目前流式获取的方式,我是暂时没有好的方式管理网络错误和音频播放结束的事件

(如果有兄弟集美们知道,还请留言赐教哈)

四、实现步骤

1、下载好SDK 导入

2、简单的搭建场景

3、写测试脚本,和普通获取和流式获取方式

4、把测试脚本添加到场景中,并赋值

 5、运行,输入文字,点击对应按钮即可

 六、关键脚本

1、Test

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. public class Test : MonoBehaviour
  4. {
  5. public InputField m_InputField;
  6. public Button m_StreamButton;
  7. public Button m_NormalButton;
  8. public AudioSource m_AudioSource;
  9. // Start is called before the first frame update
  10. void Start()
  11. {
  12. m_StreamButton.onClick.AddListener(() => {
  13. AzureTTSStream.Instance.StartTTS(m_InputField.text, m_AudioSource);
  14. });
  15. m_NormalButton.onClick.AddListener(() => {
  16. AzureTTSNormal.Instance.StartTTS(m_InputField.text, m_AudioSource);
  17. });
  18. }
  19. }

2、AzureTTSNormal

  1. using Microsoft.CognitiveServices.Speech;
  2. using System;
  3. using System.Collections;
  4. using UnityEngine;
  5. public class AzureTTSNormal : MonoSingleton<AzureTTSNormal>
  6. {
  7. private AudioSource m_AudioSource;
  8. private string m_SubscriptionKey = "Your";
  9. private string m_Region = "Your";
  10. private string m_SpeechSynthesisLanguage = "zh-CN";
  11. private string m_SpeechSynthesisVoiceName = "zh-CN-XiaochenNeural";
  12. private Coroutine m_TTSCoroutine;
  13. /// <summary>
  14. /// 你的授权
  15. /// </summary>
  16. /// <param name="subscriptionKey">子脚本的Key</param>
  17. /// <param name="region">地区</param>
  18. public void SetAzureAuthorization(string subscriptionKey, string region)
  19. {
  20. m_SubscriptionKey = subscriptionKey;
  21. m_Region = region;
  22. }
  23. /// <summary>
  24. /// 设置语音和声音
  25. /// </summary>
  26. /// <param name="language">语言</param>
  27. /// <param name="voiceName">声音</param>
  28. public void SetLanguageVoiceName(SpeechSynthesisLanguage language, SpeechSynthesisVoiceName voiceName)
  29. {
  30. m_SpeechSynthesisLanguage = language.ToString().Replace('_', '-');
  31. m_SpeechSynthesisVoiceName = voiceName.ToString().Replace('_', '-');
  32. }
  33. /// <summary>
  34. /// 设置音源
  35. /// </summary>
  36. /// <param name="audioSource"></param>
  37. public void SetAudioSource(AudioSource audioSource)
  38. {
  39. m_AudioSource = audioSource;
  40. }
  41. /// <summary>
  42. /// 开始TTS
  43. /// </summary>
  44. /// <param name="spkMsg"></param>
  45. /// <param name="errorAction"></param>
  46. public void StartTTS(string spkMsg, Action<string> errorAction = null)
  47. {
  48. StopTTS();
  49. m_TTSCoroutine = StartCoroutine(SynthesizeAudioCoroutine(spkMsg, errorAction));
  50. }
  51. /// <summary>
  52. /// 开始TTS
  53. /// </summary>
  54. /// <param name="spkMsg"></param>
  55. /// <param name="audioSource"></param>
  56. /// <param name="errorAction"></param>
  57. public void StartTTS(string spkMsg, AudioSource audioSource, Action<string> errorAction = null)
  58. {
  59. SetAudioSource(audioSource);
  60. StartTTS(spkMsg, errorAction);
  61. }
  62. /// <summary>
  63. /// 暂停TTS
  64. /// </summary>
  65. public void StopTTS()
  66. {
  67. if (m_TTSCoroutine != null)
  68. {
  69. StopCoroutine(m_TTSCoroutine);
  70. m_TTSCoroutine = null;
  71. }
  72. if (m_AudioSource != null)
  73. {
  74. m_AudioSource.Stop();
  75. m_AudioSource.clip = null;
  76. }
  77. }
  78. public IEnumerator SynthesizeAudioCoroutine(string spkMsg, Action<string> errorAction)
  79. {
  80. yield return null;
  81. var config = SpeechConfig.FromSubscription(m_SubscriptionKey, m_Region);
  82. config.SpeechSynthesisLanguage = m_SpeechSynthesisLanguage;
  83. config.SpeechSynthesisVoiceName = m_SpeechSynthesisVoiceName;
  84. // Creates a speech synthesizer.
  85. // Make sure to dispose the synthesizer after use!
  86. using (var synthsizer = new SpeechSynthesizer(config, null))
  87. {
  88. // Starts speech synthesis, and returns after a single utterance is synthesized.
  89. var result = synthsizer.SpeakTextAsync(spkMsg).Result;
  90. //print("after " + DateTime.Now);
  91. // Checks result.
  92. string newMessage = string.Empty;
  93. if (result.Reason == ResultReason.SynthesizingAudioCompleted)
  94. {
  95. // Since native playback is not yet supported on Unity yet (currently only supported on Windows/Linux Desktop),
  96. // use the Unity API to play audio here as a short term solution.
  97. // Native playback support will be added in the future release.
  98. var sampleCount = result.AudioData.Length / 2;
  99. var audioData = new float[sampleCount];
  100. for (var i = 0; i < sampleCount; ++i)
  101. {
  102. audioData[i] = (short)(result.AudioData[i * 2 + 1] << 8 | result.AudioData[i * 2]) / 32768.0F;
  103. }
  104. // The default output audio format is 16K 16bit mono
  105. var audioClip = AudioClip.Create("SynthesizedAudio", sampleCount, 1, 16000, false);
  106. audioClip.SetData(audioData, 0);
  107. m_AudioSource.clip = audioClip;
  108. Debug.Log(" audioClip.length " + audioClip.length);
  109. m_AudioSource.Play();
  110. }
  111. else if (result.Reason == ResultReason.Canceled)
  112. {
  113. var cancellation = SpeechSynthesisCancellationDetails.FromResult(result);
  114. newMessage = $"CANCELED:\nReason=[{cancellation.Reason}]\nErrorDetails=[{cancellation.ErrorDetails}]\nDid you update the subscription info?";
  115. Debug.Log(" newMessage "+ newMessage);
  116. if (errorAction!=null) { errorAction.Invoke(newMessage); }
  117. }
  118. }
  119. }
  120. }

3、AzureTTSStream

  1. using UnityEngine;
  2. using Microsoft.CognitiveServices.Speech;
  3. using System.IO;
  4. using System;
  5. using System.Collections;
  6. public class AzureTTSStream : MonoSingleton<AzureTTSStream>
  7. {
  8. private AudioSource m_AudioSource;
  9. private string m_SubscriptionKey = "Your";
  10. private string m_Region = "Your";
  11. private string m_SpeechSynthesisLanguage = "zh-CN";
  12. private string m_SpeechSynthesisVoiceName = "zh-CN-XiaochenNeural";
  13. public const int m_SampleRate = 16000;
  14. public const int m_BufferSize = m_SampleRate * 60; //最大支持60s音频,但是也可以调大,流式的无所谓
  15. public const int m_UpdateSize = m_SampleRate / 10; //采样容量,越大越卡
  16. private Coroutine m_TTSCoroutine;
  17. private int m_DataIndex = 0;
  18. private AudioDataStream m_AudioDataStream;
  19. private void OnEnable()
  20. {
  21. StopTTS();
  22. }
  23. private void OnDisable()
  24. {
  25. StopTTS();
  26. }
  27. /// <summary>
  28. /// 你的授权
  29. /// </summary>
  30. /// <param name="subscriptionKey">子脚本的Key</param>
  31. /// <param name="region">地区</param>
  32. public void SetAzureAuthorization(string subscriptionKey, string region)
  33. {
  34. m_SubscriptionKey = subscriptionKey;
  35. m_Region = region;
  36. }
  37. /// <summary>
  38. /// 设置语音和声音
  39. /// </summary>
  40. /// <param name="language">语言</param>
  41. /// <param name="voiceName">声音</param>
  42. public void SetLanguageVoiceName(SpeechSynthesisLanguage language, SpeechSynthesisVoiceName voiceName)
  43. {
  44. m_SpeechSynthesisLanguage = language.ToString().Replace('_', '-');
  45. m_SpeechSynthesisVoiceName = voiceName.ToString().Replace('_', '-');
  46. }
  47. /// <summary>
  48. /// 设置音源
  49. /// </summary>
  50. /// <param name="audioSource"></param>
  51. public void SetAudioSource(AudioSource audioSource)
  52. {
  53. m_AudioSource = audioSource;
  54. }
  55. /// <summary>
  56. /// 开始TTS
  57. /// </summary>
  58. /// <param name="spkMsg"></param>
  59. /// <param name="errorAction"></param>
  60. public void StartTTS(string spkMsg, Action<string> errorAction = null)
  61. {
  62. StopTTS();
  63. m_TTSCoroutine = StartCoroutine(SynthesizeAudioCoroutine(spkMsg, errorAction));
  64. }
  65. /// <summary>
  66. /// 开始TTS
  67. /// </summary>
  68. /// <param name="spkMsg"></param>
  69. /// <param name="audioSource"></param>
  70. /// <param name="errorAction"></param>
  71. public void StartTTS(string spkMsg, AudioSource audioSource, Action<string> errorAction = null)
  72. {
  73. SetAudioSource(audioSource);
  74. StartTTS(spkMsg, errorAction);
  75. }
  76. /// <summary>
  77. /// 暂停TTS
  78. /// </summary>
  79. public void StopTTS()
  80. {
  81. // 释放流
  82. if (m_AudioDataStream != null)
  83. {
  84. m_AudioDataStream.Dispose();
  85. m_AudioDataStream = null;
  86. }
  87. if (m_TTSCoroutine != null)
  88. {
  89. StopCoroutine(m_TTSCoroutine);
  90. m_TTSCoroutine = null;
  91. }
  92. if (m_AudioSource != null)
  93. {
  94. m_AudioSource.Stop();
  95. m_AudioSource.clip = null;
  96. m_DataIndex = 0;
  97. }
  98. }
  99. /// <summary>
  100. /// 发起TTS
  101. /// </summary>
  102. /// <param name="speakMsg">TTS的文本</param>
  103. /// <param name="errorAction">错误事件(目前没有好的判断方法)</param>
  104. /// <returns></returns>
  105. private IEnumerator SynthesizeAudioCoroutine(string speakMsg, Action<string> errorAction)
  106. {
  107. var config = SpeechConfig.FromSubscription(m_SubscriptionKey, m_Region);
  108. config.SpeechSynthesisLanguage = m_SpeechSynthesisLanguage;
  109. config.SpeechSynthesisVoiceName = m_SpeechSynthesisVoiceName;
  110. var audioClip = AudioClip.Create("SynthesizedAudio", m_BufferSize, 1, m_SampleRate, false);
  111. m_AudioSource.clip = audioClip;
  112. using (var synthesizer = new SpeechSynthesizer(config, null))
  113. {
  114. var result = synthesizer.StartSpeakingTextAsync(speakMsg);
  115. yield return new WaitUntil(() => result.IsCompleted);
  116. m_AudioSource.Play();
  117. using (m_AudioDataStream = AudioDataStream.FromResult(result.Result))
  118. {
  119. MemoryStream memStream = new MemoryStream();
  120. byte[] buffer = new byte[m_UpdateSize * 2];
  121. uint bytesRead;
  122. do
  123. {
  124. bytesRead = m_AudioDataStream.ReadData(buffer);
  125. memStream.Write(buffer, 0, (int)bytesRead);
  126. if (memStream.Length >= m_UpdateSize * 2)
  127. {
  128. var tempData = memStream.ToArray();
  129. var audioData = new float[m_UpdateSize];
  130. for (int i = 0; i < m_UpdateSize; ++i)
  131. {
  132. audioData[i] = (short)(tempData[i * 2 + 1] << 8 | tempData[i * 2]) / 32768.0F;
  133. }
  134. audioClip.SetData(audioData, m_DataIndex);
  135. m_DataIndex = (m_DataIndex + m_UpdateSize) % m_BufferSize;
  136. memStream = new MemoryStream();
  137. yield return null;
  138. }
  139. } while (bytesRead > 0);
  140. }
  141. }
  142. if (m_DataIndex == 0)
  143. {
  144. if (errorAction != null)
  145. {
  146. errorAction.Invoke(" AudioData error");
  147. }
  148. }
  149. }
  150. }
  151. /// <summary>
  152. /// 添加更多的其他语言
  153. /// 形式类似为 Zh_CN 对应 "zh-CN";
  154. /// </summary>
  155. public enum SpeechSynthesisLanguage
  156. {
  157. Zh_CN,
  158. }
  159. /// <summary>
  160. /// 添加更多的其他声音
  161. /// 形式类似为 Zh_CN_XiaochenNeural 对应 "zh-CN-XiaochenNeural";
  162. /// </summary>
  163. public enum SpeechSynthesisVoiceName
  164. {
  165. Zh_CN_XiaochenNeural,
  166. }

4、MonoSingleton

  1. using UnityEngine;
  2. public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
  3. {
  4. private static T instance;
  5. public static T Instance
  6. {
  7. get
  8. {
  9. if (instance == null)
  10. {
  11. // 查找存在的实例
  12. instance = (T)FindObjectOfType(typeof(T));
  13. // 如果不存在实例,则创建
  14. if (instance == null)
  15. {
  16. // 需要创建一个游戏对象,再把这个单例组件挂载到游戏对象上
  17. var singletonObject = new GameObject();
  18. instance = singletonObject.AddComponent<T>();
  19. singletonObject.name = typeof(T).ToString() + " (Singleton)";
  20. // 让实例不在切换场景时销毁
  21. DontDestroyOnLoad(singletonObject);
  22. }
  23. }
  24. return instance;
  25. }
  26. }
  27. }

优化流式读取数据的卡顿

  1. using FfalconXR;
  2. using Microsoft.CognitiveServices.Speech;
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using System.Threading.Tasks;
  7. using System.Threading;
  8. using UnityEngine;
  9. public class AzureTTSStream : MonoSingleton<AzureTTSStream>
  10. {
  11. const string TAG = "【Unity AzureTTS】";
  12. bool m_IsShowLog=true;
  13. private AudioSource m_AudioSource;
  14. private string m_SubscriptionKey = "YOUR_KEY";
  15. private string m_Region = "eastasia";
  16. private string m_SpeechSynthesisLanguage = "zh-CN"; //"zh-cn-sichuan";
  17. private string m_SpeechSynthesisVoiceName = "zh-CN-XiaochenNeural"; // "zh-cn-sichuan-YunxiNeural"; //"zh-cn-shaanxi-XiaoniNeural";
  18. public const int m_SampleRate = 16000;
  19. public const int m_BufferSize = m_SampleRate * 60; //最大支持60s音频,但是也可以调大,流式的无所谓
  20. public const int m_UpdateSize = m_SampleRate / 10; //采样容量,越大越卡
  21. private Coroutine m_TTSCoroutine;
  22. private int m_DataIndex = 0;
  23. private SpeechConfig m_SpeechConfig;
  24. private AudioDataStream m_AudioDataStream;
  25. private Task m_Task;
  26. private CancellationTokenSource m_CancellationTokenSource;
  27. private SpeechSynthesizer m_SpeechSynthesizer;
  28. private bool m_IsSpeechSynthesizerInitialized;
  29. protected override void Awake()
  30. {
  31. base.Awake();
  32. m_SpeechConfig = SpeechConfig.FromSubscription(m_SubscriptionKey, m_Region);
  33. m_SpeechConfig.SpeechSynthesisLanguage = m_SpeechSynthesisLanguage;
  34. m_SpeechConfig.SpeechSynthesisVoiceName = m_SpeechSynthesisVoiceName;
  35. }
  36. private void Start()
  37. {
  38. InitializeSpeechSynthesizer();
  39. }
  40. private void OnEnable()
  41. {
  42. StopTTS();
  43. }
  44. private void OnDisable()
  45. {
  46. StopTTS();
  47. }
  48. protected override void OnDestroy()
  49. {
  50. StopTTS();
  51. DisposeSpeechSynthesizer();
  52. }
  53. public void SetAzureAuthorization(string subscriptionKey, string region) {
  54. m_SubscriptionKey= subscriptionKey;
  55. m_Region= region;
  56. }
  57. public void SetLanguageVoiceName(SpeechSynthesisLanguage language, SpeechSynthesisVoiceName voiceName)
  58. {
  59. m_SpeechSynthesisLanguage = language.ToString().Replace('_','-');
  60. m_SpeechSynthesisVoiceName = voiceName.ToString().Replace('_', '-');
  61. Debug.Log(" m_SpeechSynthesisLanguage " + m_SpeechSynthesisLanguage);
  62. Debug.Log(" m_SpeechSynthesisVoiceName " + m_SpeechSynthesisVoiceName);
  63. }
  64. public void SetAudioSource(AudioSource audioSource)
  65. {
  66. m_AudioSource= audioSource;
  67. }
  68. public async void StartTTS(string spkMsg, Action startAction, Action<string> errorAction=null)
  69. {
  70. StopTTS();
  71. //m_TTSCoroutine = StartCoroutine(SynthesizeAudioCoroutine(spkMsg, startAction, errorAction));
  72. await SynthesizeAudioAsync(spkMsg, startAction, errorAction);
  73. }
  74. public void StartTTS(string spkMsg, AudioSource audioSource, Action startAction, Action<string> errorAction=null)
  75. {
  76. SetAudioSource(audioSource);
  77. StartTTS(spkMsg, startAction, errorAction);
  78. }
  79. public void StopTTS()
  80. {
  81. // 释放流
  82. if (m_AudioDataStream != null)
  83. {
  84. m_AudioDataStream.Dispose();
  85. m_AudioDataStream = null;
  86. }
  87. if (m_CancellationTokenSource != null)
  88. {
  89. m_CancellationTokenSource.Cancel();
  90. }
  91. if (m_TTSCoroutine != null)
  92. {
  93. StopCoroutine(m_TTSCoroutine);
  94. m_TTSCoroutine = null;
  95. }
  96. if (m_AudioSource!=null)
  97. {
  98. m_AudioSource.Stop();
  99. m_AudioSource.clip = null;
  100. m_DataIndex = 0;
  101. }
  102. }
  103. /// <summary>
  104. /// 发起TTS
  105. /// </summary>
  106. /// <param name="speakMsg">TTS的文本</param>
  107. /// <param name="errorAction">错误事件(目前没有好的判断方法)</param>
  108. /// <returns></returns>
  109. private IEnumerator SynthesizeAudioCoroutine(string speakMsg, Action startAction,Action<string> errorAction)
  110. {
  111. var audioClip = AudioClip.Create("SynthesizedAudio", m_BufferSize, 1, m_SampleRate, false);
  112. m_AudioSource.clip = audioClip;
  113. startAction?.Invoke();
  114. using (var synthesizer = new SpeechSynthesizer(m_SpeechConfig, null))
  115. {
  116. var result = synthesizer.StartSpeakingTextAsync(speakMsg);
  117. yield return new WaitUntil(() => result.IsCompleted);
  118. m_AudioSource.Play();
  119. using (m_AudioDataStream = AudioDataStream.FromResult(result.Result))
  120. {
  121. MemoryStream memStream = new MemoryStream();
  122. byte[] buffer = new byte[m_UpdateSize * 2];
  123. uint bytesRead;
  124. do
  125. {
  126. bytesRead = m_AudioDataStream.ReadData(buffer);
  127. memStream.Write(buffer, 0, (int)bytesRead);
  128. if (memStream.Length >= m_UpdateSize * 2)
  129. {
  130. var tempData = memStream.ToArray();
  131. var audioData = new float[m_UpdateSize];
  132. for (int i = 0; i < m_UpdateSize; ++i)
  133. {
  134. audioData[i] = (short)(tempData[i * 2 + 1] << 8 | tempData[i * 2]) / 32768.0F;
  135. }
  136. audioClip.SetData(audioData, m_DataIndex);
  137. m_DataIndex = (m_DataIndex + m_UpdateSize) % m_BufferSize;
  138. memStream = new MemoryStream();
  139. yield return null;
  140. }
  141. } while (bytesRead > 0);
  142. }
  143. }
  144. if (m_DataIndex==0) {
  145. if (errorAction!=null)
  146. {
  147. errorAction.Invoke(" AudioData error");
  148. }
  149. }
  150. }
  151. /// <summary>
  152. /// async 方式
  153. /// </summary>
  154. /// <param name="speakMsg"></param>
  155. /// <param name="startAction"></param>
  156. /// <param name="errorAction"></param>
  157. private async Task SynthesizeAudioAsync(string speakMsg, Action startAction, Action<string> errorAction) {
  158. StopTTS();
  159. m_CancellationTokenSource = new CancellationTokenSource();
  160. if (!m_IsSpeechSynthesizerInitialized)
  161. {
  162. // 如果 SpeechSynthesizer 尚未初始化,则在需要时进行初始化
  163. InitializeSpeechSynthesizer();
  164. }
  165. try
  166. {
  167. using (var result = await m_SpeechSynthesizer.StartSpeakingTextAsync(speakMsg))
  168. {
  169. using (m_AudioDataStream = AudioDataStream.FromResult(result))
  170. {
  171. var audioClip = AudioClip.Create("SynthesizedAudio", m_BufferSize, 1, m_SampleRate, false);
  172. m_AudioSource.clip = audioClip;
  173. startAction?.Invoke();
  174. MemoryStream memStream = new MemoryStream();
  175. byte[] buffer = new byte[m_UpdateSize * 2];
  176. uint bytesRead = 0;
  177. do
  178. {
  179. if (m_CancellationTokenSource.IsCancellationRequested)
  180. {
  181. break; // 取消操作,退出循环
  182. }
  183. bytesRead = await Task.Run(() => m_AudioDataStream.ReadData(buffer));
  184. if (m_IsShowLog) Debug.Log(TAG + $"{bytesRead} bytes received.");
  185. await memStream.WriteAsync(buffer, 0, (int)bytesRead);
  186. if (memStream.Length >= m_UpdateSize * 2)
  187. {
  188. var tempData = memStream.ToArray();
  189. var audioData = new float[m_UpdateSize];
  190. for (int i = 0; i < m_UpdateSize; ++i)
  191. {
  192. audioData[i] = (short)(tempData[i * 2 + 1] << 8 | tempData[i * 2]) / 32768.0F;
  193. }
  194. audioClip.SetData(audioData, m_DataIndex);
  195. m_DataIndex = (m_DataIndex + m_UpdateSize) % m_BufferSize;
  196. if (m_AudioSource.isPlaying == false)
  197. {
  198. m_AudioSource.Play();
  199. }
  200. memStream = new MemoryStream();
  201. }
  202. await Task.Yield(); // 让出一帧的时间给主线程
  203. } while (bytesRead > 0);
  204. }
  205. }
  206. }
  207. catch (Exception e)
  208. {
  209. if (m_IsShowLog) Debug.Log(TAG + e.Message);
  210. }
  211. }
  212. private void InitializeSpeechSynthesizer()
  213. {
  214. var config = SpeechConfig.FromSubscription(m_SubscriptionKey, m_Region);
  215. config.SpeechSynthesisLanguage = m_SpeechSynthesisLanguage;
  216. config.SpeechSynthesisVoiceName = m_SpeechSynthesisVoiceName;
  217. m_SpeechSynthesizer = new SpeechSynthesizer(config, null);
  218. m_IsSpeechSynthesizerInitialized = true;
  219. }
  220. private void DisposeSpeechSynthesizer()
  221. {
  222. // 停止语音合成并释放资源
  223. if (m_SpeechSynthesizer != null)
  224. {
  225. m_SpeechSynthesizer.StopSpeakingAsync();
  226. m_SpeechSynthesizer.Dispose();
  227. m_SpeechSynthesizer = null;
  228. m_IsSpeechSynthesizerInitialized = false;
  229. }
  230. }
  231. }
  232. public enum SpeechSynthesisLanguage {
  233. Zh_CN,
  234. zh_cn_sichuan
  235. }
  236. public enum SpeechSynthesisVoiceName {
  237. Zh_CN_XiaochenNeural,
  238. }

附加:

声音设置相关

语言支持 - 语音服务 - Azure Cognitive Services | Azure Docs

中国部分声音选择设置:

wuu-CN中文(吴语,简体)wuu-CN-XiaotongNeural1,2(女)
wuu-CN-YunzheNeural1,2(男)
yue-CN中文(粤语,简体)yue-CN-XiaoMinNeural1,2(女)
yue-CN-YunSongNeural1,2(男)
zh-cn中文(普通话,简体)zh-cn-XiaochenNeural(女)
zh-cn-XiaohanNeural(女)
zh-cn-XiaomengNeural(女)
zh-cn-XiaomoNeural(女)
zh-cn-XiaoqiuNeural(女)
zh-cn-XiaoruiNeural(女)
zh-cn-XiaoshuangNeural(女性、儿童)
zh-cn-XiaoxiaoNeural(女)
zh-cn-XiaoxuanNeural(女)
zh-cn-XiaoyanNeural(女)
zh-cn-XiaoyiNeural(女)
zh-cn-XiaoyouNeural(女性、儿童)
zh-cn-XiaozhenNeural(女)
zh-cn-YunfengNeural(男)
zh-cn-YunhaoNeural(男)
zh-cn-YunjianNeural(男)
zh-cn-YunxiaNeural(男)
zh-cn-YunxiNeural(男)
zh-cn-YunyangNeural(男)
zh-cn-YunyeNeural(男)
zh-cn-YunzeNeural(男)
zh-cn-henan中文(中原官话河南,简体)zh-cn-henan-YundengNeural2(男)
zh-cn-liaoning中文(东北官话,简体)zh-cn-liaoning-XiaobeiNeural1,2(女)
zh-cn-shaanxi中文(中原官话陕西,简体)zh-cn-shaanxi-XiaoniNeural1,2(女)
zh-cn-shandong中文(冀鲁官话,简体)zh-cn-shandong-YunxiangNeural2(男)
zh-cn-sichuan中文(西南普通话,简体)zh-cn-sichuan-YunxiNeural1,2(男)
zh-HK中文(粤语,繁体)zh-HK-HiuGaaiNeural(女)
zh-HK-HiuMaanNeural(女)
zh-HK-WanLungNeural1(男)
zh-TW中文(台湾普通话,繁体)zh-TW-HsiaoChenNeural(女)
zh-TW-HsiaoYuNeural(女)
zh-TW-YunJheNeural(男)
zu-ZA祖鲁语(南非)zu-ZA-ThandoNeural2(女)
zu-ZA-ThembaNeural2(男)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/135574
推荐阅读
相关标签
  

闽ICP备14008679号