Unity集成阿里云语音AI:从录音到文本的实时转换实战

张开发
2026/5/4 16:58:05 15 分钟阅读
Unity集成阿里云语音AI:从录音到文本的实时转换实战
1. 为什么选择阿里云语音AI与Unity结合在游戏开发或交互式应用中实时语音转文字的需求越来越普遍。比如玩家语音指令控制角色、会议记录自动生成字幕、教育类应用的语音评测等场景。阿里云的智能语音交互服务Intelligent Speech Interaction提供了高精度的**语音转文字ASR和文字转语音TTS**能力而Unity作为跨平台引擎两者结合能快速实现高质量的语音交互功能。实测下来阿里云语音识别有三大优势首先是识别准确率高中文普通话场景下能达到95%以上其次是响应速度快平均延迟在300ms左右最后是支持多种音频格式包括PCM、WAV、OPUS等。对于Unity开发者来说这套方案比自建语音识别模型成本低得多——你不需要训练声学模型、语言模型也不用担心服务器负载问题。2. 环境准备与SDK接入2.1 阿里云账号配置首先登录阿里云控制台在智能语音交互产品页开通服务。重点获取两个参数AccessKey ID和AccessKey Secret在控制台AccessKey管理页面创建AppKey在语音交互项目的应用管理中创建应用后获得注意AccessKey权限建议按最小化原则只授予智能语音交互NLS的访问权限避免泄露风险。2.2 Unity工程设置在Unity中新建C#脚本AliyunVoiceSDK.cs核心结构如下public class AliyunVoiceSDK : MonoBehaviour { public static AliyunVoiceSDK Instance; private string Token { get; set; } private long ExpireTime { get; set; } private string Appkey 你的AppKey; void Awake() { if (Instance null) { Instance this; DontDestroyOnLoad(gameObject); } Init(); } }需要安装这些依赖库Newtonsoft.Json通过Unity Package Manager安装UnityWebRequestUnity内置网络模块3. 获取动态Token实战阿里云要求每次语音识别前必须先获取临时Token。这个Token有效期通常为1小时过期后需要重新获取。下面是完整实现public void SendGetVoiceSdkToken() { Dictionarystring, string queryParams new Dictionarystring, string { {AccessKeyId, 你的AccessKey ID}, {Action, CreateToken}, {Version, 2019-02-28}, {Timestamp, DateTime.UtcNow.ToString(yyyy-MM-ddTHH:mm:ssZ)}, {Format, JSON}, {RegionId, cn-shanghai}, {SignatureMethod, HMAC-SHA1}, {SignatureVersion, 1.0}, {SignatureNonce, Guid.NewGuid().ToString()} }; // 1. 参数排序与编码 string queryString CanonicalizedQuery(queryParams); // 2. 构造签名字符串 string stringToSign CreateStringToSign(GET, /, queryString); // 3. 计算签名 string signature Sign(stringToSign, 你的AccessKey Secret); // 4. 发送请求 StartCoroutine(ProcessGETRequest(queryString Signature signature)); } private string Sign(string stringToSign, string accessKeySecret) { using (HMACSHA1 hmac new HMACSHA1(Encoding.UTF8.GetBytes(accessKeySecret ))) { byte[] hashBytes hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)); return Convert.ToBase64String(hashBytes); } }常见坑点时间戳必须用UTC时间本地时间会导致签名错误SignatureNonce每次请求必须唯一用GUID是个好选择参数排序要严格按照字母序错位会导致签名失败4. 实时语音转文字全流程4.1 麦克风录音采集Unity的Microphone类可以直接获取设备音频输入AudioClip MicrophoneClip; string CurrentDeviceName null; IEnumerator StartRecording() { // 获取默认麦克风 CurrentDeviceName Microphone.devices[0]; // 开始录音16kHz采样率单声道最长60秒 MicrophoneClip Microphone.Start(CurrentDeviceName, true, 60, 16000); // 等待录音真正开始 while (!(Microphone.GetPosition(CurrentDeviceName) 0)) { yield return null; } // 这里可以添加UI提示录音中... }4.2 音频格式转换阿里云API要求音频为PCM或WAV格式。使用WavUtility工具类转换IEnumerator ProcessRecording() { // 停止录音 Microphone.End(CurrentDeviceName); // 转换为WAV字节流 byte[] wavBytes WavUtility.FromAudioClip(MicrophoneClip); // 发送到阿里云 yield return AliyunVoiceSDK.Instance.ProcessVoiceData( wavBytes, wav, 16000, true, // 开启标点预测 true // 开启ITN数字转文字 ); }关键参数说明sampleRate必须与录音时一致推荐16000enablePunctuationPrediction自动添加句号逗号enableInverseTextNormalization把123转为一百二十三4.3 处理识别结果阿里云返回的JSON结构示例{ result: 今天天气真好, status: 20000000 }在Unity中解析结果if (request.result UnityWebRequest.Result.Success) { JObject obj JObject.Parse(request.downloadHandler.text); string textResult obj[result].ToString(); Debug.Log(识别结果 textResult); // 这里可以更新UI字幕或触发游戏事件 }5. 文字转语音实现5.1 语音合成API调用IEnumerator TextToSpeech(string text, AudioSource speaker) { string url https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts; JObject body new JObject { {appkey, Appkey}, {token, Token}, {text, text}, {format, wav}, {sample_rate, 16000}, {voice, xiaoyun}, // 可选发音人 {volume, 50} // 音量0-100 }; UnityWebRequest request new UnityWebRequest(url, POST); request.uploadHandler new UploadHandlerRaw(Encoding.UTF8.GetBytes(body.ToString())); request.downloadHandler new DownloadHandlerBuffer(); request.SetRequestHeader(Content-Type, application/json); yield return request.SendWebRequest(); if (request.result UnityWebRequest.Result.Success) { StartCoroutine(PlayAudio(request.downloadHandler.data, speaker)); } }5.2 音频数据播放将返回的WAV数据转为AudioClipIEnumerator PlayAudio(byte[] wavData, AudioSource speaker) { // 跳过WAV文件头前44字节 byte[] audioData new byte[wavData.Length - 44]; Array.Copy(wavData, 44, audioData, 0, audioData.Length); // 转换为float数组 float[] samples new float[audioData.Length / 2]; for (int i 0; i samples.Length; i) { short value (short)((audioData[i*21] 8) | audioData[i*2]); samples[i] value / 32768.0f; } // 创建AudioClip AudioClip clip AudioClip.Create(TTS, samples.Length, 1, 16000, false); clip.SetData(samples, 0); // 播放 speaker.clip clip; speaker.Play(); }6. 错误处理与优化建议6.1 常见错误码错误码含义解决方案40000001Token过期重新获取Token40000003无效AppKey检查控制台应用配置40000005音频格式不支持确认使用PCM/WAV/OPUS40000007采样率不匹配确保录音与请求参数一致6.2 性能优化技巧Token缓存获取Token后记录时间提前30分钟刷新音频分块长时间录音建议每5秒发送一次请求降噪处理在录音前调用Application.RequestMicrophonePermission()确保权限备选方案当阿里云服务不可用时可切换本地识别如Unity的UnityEngine.Windows.Speech// Token缓存示例 private IEnumerator CheckToken() { while (true) { if (DateTime.Now.Ticks ExpireTime * 10000 - 1800000000) { SendGetVoiceSdkToken(); } yield return new WaitForSeconds(60); } }7. 完整项目结构建议一个可维护的Unity语音项目应该这样组织Assets/ ├─ Scripts/ │ ├─ AliyunVoiceSDK.cs # 核心API封装 │ ├─ AudioRecorder.cs # 录音控制 │ └─ TTSSpeaker.cs # 语音播放 ├─ Plugins/ │ └─ Newtonsoft.Json.dll # JSON解析 └─ Scenes/ └─ Main.unity # 测试场景在真实项目中我会把语音功能封装成独立Prefab包含麦克风权限检测UI录音按钮与波形显示实时字幕文本框错误提示面板这种架构既方便单独测试也能直接拖入其他项目复用。记得在OnDestroy里停止所有Coroutine避免资源泄漏。

更多文章