基于Twilio+OpenAI的电话聊天Bot长音频播放失败问题排查
问题排查与解决方案
核心原因分析
Twilio对Webhook请求有默认超时限制(15秒),当生成较长音频时,OpenAI TTS处理+音频返回的总耗时超过这个阈值,就会触发11200(HTTP检索失败)或11205(连接超时)错误。短音频处理耗时在超时范围内,所以能正常响应。
具体排查与修复步骤
1. 调整Twilio超时配置
Twilio允许将Webhook超时最大调整到120秒,先在控制台修改:
- 进入Twilio控制台,找到目标号码
- 进入「Voice & Fax」模块,查看「A call comes in」的配置项
- 将「Timeout」值调整为120秒
注:即使调大超时,若服务器处理耗时超过120秒仍会失败,需配合后续优化
2. 改用异步音频生成+临时存储方案
直接在Flask路由中同步生成并返回长音频会阻塞请求,导致Twilio超时。建议先将音频上传到临时存储,再返回Twilio可直接访问的URL:
示例代码调整(Flask):
from flask import Flask, request, Response import openai import threading from twilio.twiml.voice_response import VoiceResponse, Play app = Flask(__name__) # 模拟本地临时存储(生产环境建议用云存储如S3) temp_audio_store = {} def generate_audio(text, call_sid): # 生成TTS音频 response = openai.audio.speech.create( model="tts-1", voice="alloy", input=text, timeout=30 ) # 将音频字节存入临时存储 temp_audio_store[call_sid] = response.read() @app.route("/voice", methods=['POST']) def voice(): call_sid = request.form['CallSid'] # 省略Whisper转写、ChatGPT生成回复的代码 gpt_long_response = "用户的长文本回复内容" # 开启线程异步生成音频,不阻塞当前请求 threading.Thread(target=generate_audio, args=(gpt_long_response, call_sid)).start() # 返回Twilio指令:先播放等待提示,再重定向获取音频 resp = VoiceResponse() resp.play("https://your-ngrok-domain/waiting_tone.mp3") resp.redirect(f"/fetch_audio?call_sid={call_sid}") return Response(str(resp), mimetype='application/xml') @app.route("/fetch_audio", methods=['POST']) def fetch_audio(): call_sid = request.args.get('call_sid') if call_sid in temp_audio_store: # 返回音频内容 return Response(temp_audio_store[call_sid], mimetype='audio/mpeg') else: # 音频未生成完成,返回等待提示并重定向重试 resp = VoiceResponse() resp.play("https://your-ngrok-domain/waiting_tone.mp3") resp.redirect(f"/fetch_audio?call_sid={call_sid}") return Response(str(resp), mimetype='application/xml')
3. 优化音频生成效率
- 调整OpenAI TTS参数,通过提高语速缩短音频时长:
response = openai.audio.speech.create( model="tts-1", voice="alloy", input=gpt_response, speed=1.2 # 提高语速,减少音频生成时间和文件长度 )
- 将超长文本分割为多个片段,生成多段音频后用Twilio的多个
<Play>指令依次播放
4. 检查ngrok限制
免费版ngrok有连接时长和带宽限制,长音频传输可能触发中断:
- 升级ngrok到付费版,获得更长连接时长和更高带宽
- 确保ngrok隧道保持活跃,避免因长时间无流量被自动断开
5. 启用Flask异步模式
Flask 2.0+支持异步路由,可减少请求阻塞:
@app.route("/voice", methods=['POST']) async def voice(): # 异步执行音频生成逻辑 # ... 其余代码调整为异步写法
内容的提问来源于stack exchange,提问作者David A.
相关产品推荐
相关产品推荐

