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


    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. ///
    14. /// 你的授权
    15. ///
    16. /// 子脚本的Key
    17. /// 地区
    18. public void SetAzureAuthorization(string subscriptionKey, string region)
    19. {
    20. m_SubscriptionKey = subscriptionKey;
    21. m_Region = region;
    22. }
    23. ///
    24. /// 设置语音和声音
    25. ///
    26. /// 语言
    27. /// 声音
    28. public void SetLanguageVoiceName(SpeechSynthesisLanguage language, SpeechSynthesisVoiceName voiceName)
    29. {
    30. m_SpeechSynthesisLanguage = language.ToString().Replace('_', '-');
    31. m_SpeechSynthesisVoiceName = voiceName.ToString().Replace('_', '-');
    32. }
    33. ///
    34. /// 设置音源
    35. ///
    36. ///
    37. public void SetAudioSource(AudioSource audioSource)
    38. {
    39. m_AudioSource = audioSource;
    40. }
    41. ///
    42. /// 开始TTS
    43. ///
    44. ///
    45. ///
    46. public void StartTTS(string spkMsg, Action<string> errorAction = null)
    47. {
    48. StopTTS();
    49. m_TTSCoroutine = StartCoroutine(SynthesizeAudioCoroutine(spkMsg, errorAction));
    50. }
    51. ///
    52. /// 开始TTS
    53. ///
    54. ///
    55. ///
    56. ///
    57. public void StartTTS(string spkMsg, AudioSource audioSource, Action<string> errorAction = null)
    58. {
    59. SetAudioSource(audioSource);
    60. StartTTS(spkMsg, errorAction);
    61. }
    62. ///
    63. /// 暂停TTS
    64. ///
    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. ///
    28. /// 你的授权
    29. ///
    30. /// 子脚本的Key
    31. /// 地区
    32. public void SetAzureAuthorization(string subscriptionKey, string region)
    33. {
    34. m_SubscriptionKey = subscriptionKey;
    35. m_Region = region;
    36. }
    37. ///
    38. /// 设置语音和声音
    39. ///
    40. /// 语言
    41. /// 声音
    42. public void SetLanguageVoiceName(SpeechSynthesisLanguage language, SpeechSynthesisVoiceName voiceName)
    43. {
    44. m_SpeechSynthesisLanguage = language.ToString().Replace('_', '-');
    45. m_SpeechSynthesisVoiceName = voiceName.ToString().Replace('_', '-');
    46. }
    47. ///
    48. /// 设置音源
    49. ///
    50. ///
    51. public void SetAudioSource(AudioSource audioSource)
    52. {
    53. m_AudioSource = audioSource;
    54. }
    55. ///
    56. /// 开始TTS
    57. ///
    58. ///
    59. ///
    60. public void StartTTS(string spkMsg, Action<string> errorAction = null)
    61. {
    62. StopTTS();
    63. m_TTSCoroutine = StartCoroutine(SynthesizeAudioCoroutine(spkMsg, errorAction));
    64. }
    65. ///
    66. /// 开始TTS
    67. ///
    68. ///
    69. ///
    70. ///
    71. public void StartTTS(string spkMsg, AudioSource audioSource, Action<string> errorAction = null)
    72. {
    73. SetAudioSource(audioSource);
    74. StartTTS(spkMsg, errorAction);
    75. }
    76. ///
    77. /// 暂停TTS
    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_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. ///
    100. /// 发起TTS
    101. ///
    102. /// TTS的文本
    103. /// 错误事件(目前没有好的判断方法)
    104. ///
    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. ///
    152. /// 添加更多的其他语言
    153. /// 形式类似为 Zh_CN 对应 "zh-CN";
    154. ///
    155. public enum SpeechSynthesisLanguage
    156. {
    157. Zh_CN,
    158. }
    159. ///
    160. /// 添加更多的其他声音
    161. /// 形式类似为 Zh_CN_XiaochenNeural 对应 "zh-CN-XiaochenNeural";
    162. ///
    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();
    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. ///
    104. /// 发起TTS
    105. ///
    106. /// TTS的文本
    107. /// 错误事件(目前没有好的判断方法)
    108. ///
    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. ///
    152. /// async 方式
    153. ///
    154. ///
    155. ///
    156. ///
    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(男)
  • 相关阅读:
    若依框架下首次写接口
    汉语言文学类毕业论文,有什么好写的选题?
    EasyExcel的使用
    基于R和gephi做宏基因组与代谢组等多组学联合network相关性网络图
    企业完善质量、环境、健康安全三体系认证的作用及其意义!
    鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:形状裁剪)
    Mac,Windows11,Windows10局域网互传共享文件
    德博能源、西门子能源、霍尼韦尔等出席2023中国可持续生物燃料峰会
    YOLOv7训练自己的数据集
    高阶python | 装饰器
  • 原文地址:https://blog.csdn.net/u014361280/article/details/130902485