Flask编码Azure语音合成音频为字符串,JS解码播放失败排查
问题分析与代码修正
一、前端JavaScript代码错误
你在JS里犯了变量名大小写不匹配的低级错误:
- 定义的变量是
audio_data,但解码时误用了audioData,这会导致audioData未定义,后续二进制解码、Blob创建全流程失败,自然无法播放音频。
修正后的JS代码片段:
$.post("/retrieve_speech", { text: "This is a test" }).done(function (data) { var audio_data= data.audio_data; var speech_timing = data.speech_timing; var other = data.other; // 修正变量名:使用audio_data而非audioData var binaryData = atob(audio_data); var byteArray = new Uint8Array(binaryData.length); for(var i = 0; i < binaryData.length; i++) { byteArray[i] = binaryData.charCodeAt(i); } var blob = new Blob([byteArray], {type: 'audio/wav'}); var url = URL.createObjectURL(blob); var audio = new Audio(url); audio.play(); });
二、Flask后端代码问题
1. 未处理异常分支的变量初始化
当Azure语音合成被取消(Canceled分支)时,data和speech_timing变量未定义,直接返回jsonify会抛出NameError,导致前端收到500错误。
修正:在函数开头初始化这两个变量:
@app.route("/retrieve_speech", methods=['POST']) def retrieve_speech(): text= request.form.get('text') start = time.time() # 初始化变量,避免分支未覆盖导致的未定义错误 data = "" speech_timing = "0" speech_key = "my key" # ... 后续代码不变
2. 冗余的格式转换(引发Numba警告+额外出错风险)
你先让Azure生成MP3格式,再用AudioSegment转成WAV,完全是多此一举:
- Azure文本转语音可以直接生成WAV格式音频,跳过转换步骤能避免
pydub/Numba的多线程兼容问题,还能提升性能。
修改输出格式为直接生成WAV:
speech_config.set_speech_synthesis_output_format( # 直接生成WAV格式,无需后续转换 speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm )
同时去掉MP3转WAV的代码块,直接处理Azure返回的WAV数据:
if result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted: # 直接使用Azure返回的WAV数据,跳过格式转换 data = io.BytesIO(result.audio_data) data.seek(0) data = base64.b64encode(data.read()).decode('utf-8') speech_timing = time.time() - start # ... 后续分支代码不变
三、Numba警告的解决
你看到的Numba: Attempted to fork from a non-main thread...警告,是因为Flask默认多线程服务器与pydub依赖的Numba TBB库不兼容。上面的修正(直接生成WAV,不用AudioSegment)会直接消除这个警告,因为不再触发Numba的代码路径。
如果一定要保留格式转换步骤,也可以:
- 启动Flask时用单线程模式:
flask run --threaded=False - 或者在代码开头禁用Numba多线程:
import numba numba.set_num_threads(1)
内容的提问来源于stack exchange,提问作者BlackHawk
相关产品推荐
相关产品推荐

