Azure App Service部署认知服务TTS API时SpeechSynthesizer初始化失败
解决Azure App Service上文本转语音API的SPXERR_AUDIO_SYS_LIBRARY_NOT_FOUND错误
问题场景
本地运行文本转语音API一切正常,但发布到Azure App Service后,调用端点时初始化SpeechSynthesizer出现错误代码0x38(SPXERR_AUDIO_SYS_LIBRARY_NOT_FOUND),触发点在调用GetVoice方法设置SpeechSynthesisVoiceName的过程中。
问题原因
Azure App Service的Windows宿主环境没有预装音频驱动及相关系统库,当创建SpeechSynthesizer时如果不指定空音频配置,SDK会尝试加载音频输出组件,导致找不到依赖库抛出错误。此外代码中还存在异步调用使用.Result可能引发死锁、存储路径权限不足的潜在问题。
解决方案
1. 修改GetVoice方法,使用空音频配置
获取语音列表不需要实际输出音频,因此创建SpeechSynthesizer时传入AudioConfig.FromNull(),跳过音频设备初始化:
public static async Task<VoiceInfo> GetVoice(this SpeechConfig config, string localeid) { // 传入空音频配置,避免加载音频系统依赖 using (var synthesizer = new SpeechSynthesizer(config, AudioConfig.FromNull())) { using (var voices = await synthesizer.GetVoicesAsync()) { var voice = voices.Voices.FirstOrDefault(voice => voice.Locale == localeid) ?? voices.Voices.First(voice => voice.Locale == defaultLocale); return voice; } } }
2. 替换.Result为await,避免死锁
异步方法中使用.Result会阻塞线程,在ASP.NET环境易引发死锁,修改调用逻辑为:
try { // 改用await调用异步方法 _config.SpeechSynthesisVoiceName = (await _config.GetVoice(localeid)).ShortName; } catch (Exception ex) { _logger.LogError($"Error getting voice for {localeid}: {ex.Message}, Stack: {ex.StackTrace}"); throw; }
3. 更换音频文件存储路径到临时目录
CommonApplicationData目录在App Service中可能没有写入权限,改用系统临时目录存储生成的音频文件,同时使用后删除临时文件避免空间占用:
// 使用临时目录存储音频文件 string audioPath = Path.Combine(Path.GetTempPath(), $"{text.GetHashCode()}-{localeid}.wav"); _logger.LogInformation($"AudioPath: {audioPath}"); // ... 生成音频逻辑 ... if (!response.HasError) { response.Wave = System.IO.File.ReadAllBytes(audioPath); // 删除临时文件 System.IO.File.Delete(audioPath); }
内容的提问来源于stack exchange,提问作者Hans-Henrik Møller
相关产品推荐
相关产品推荐

