使用Twilio Action参数请求录音时出现500错误(11200&12200)排查
问题原因
- 触发时机差异:
- 使用
action="/handle_audio"时,Twilio会在录制动作结束的瞬间立即调用该端点,但此时录音文件还处于Twilio后台处理流程中,并未完全生成并对外可访问,直接请求RecordingUrl自然返回404。 recording_status_callback="/handle_audio"则是在录音完全处理完成、文件就绪后才触发,此时RecordingUrl有效,能正常下载音频。
- 使用
- 错误对应:
- Twilio控制台的11200错误表示HTTP请求失败,12200错误表示目标URL不可达,本质都是因为提前请求了未就绪的录音资源导致的。
修复方案
需要明确两个参数的分工:action负责返回后续通话的TwiML(比如播报转写结果),recording_status_callback负责处理录音转写逻辑,通过缓存或数据库传递转写结果。
步骤1:修改来电处理端点,分离两个参数的职责
@app.route('/incoming_call', methods=['POST']) def handle_call(): response = VoiceResponse() response.play("./static/audio/intro.mp3") # 分别指定action和recording_status_callback response.record( action="/post_recording", # 录制结束后返回TwiML继续通话流程 recording_status_callback="/handle_audio", # 录音就绪后处理转写 recording_status_callback_event="completed", recording_format='mp3', timeout=3, play_beep=False ) return Response(str(response), 200, mimetype='application/xml')
步骤2:新增/post_recording端点,等待转写结果并播报
此端点负责在录制结束后,等待转写完成并向用户播报结果(示例使用Redis缓存轮询,实际可根据需求改用异步通知):
from flask import request from twilio.twiml.voice_response import VoiceResponse, Say import time import redis # 初始化Redis缓存,需提前安装redis库并启动服务 cache = redis.Redis(host='localhost', port=6379, db=0) @app.route('/post_recording', methods=['POST']) def post_recording(): recording_sid = request.values.get('RecordingSid') response = VoiceResponse() response.say("正在处理您的录音,请稍候...") # 轮询缓存获取转写结果(最多等待10秒) wait_count = 0 transcription = None while wait_count < 10: transcription = cache.get(f"transcript_{recording_sid}") if transcription: transcription = transcription.decode('utf-8') break time.sleep(1) wait_count += 1 if transcription: response.say(f"您的录音转写结果是:{transcription}") else: response.say("转写超时,请稍后再试") return Response(str(response), 200, mimetype='application/xml')
步骤3:修改/handle_audio端点,完成转写并存储结果
@app.route('/handle_audio', methods=['POST']) def transcribe_audio(): audio_url = request.values.get('RecordingUrl') recording_sid = request.values.get('RecordingSid') credentials = f"{accSID}:{accAUTH}" encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8') headers = { 'Authorization': f'Basic {encoded_credentials}' } # 下载音频文件 audio_response = requests.get(f"{audio_url}.mp3", headers=headers, stream=True) audio_response.raise_for_status() # 替换为你的实际转写逻辑(比如调用OpenAI Whisper、第三方ASR服务等) transcription = "这是一段测试录音的转写内容" # 将转写结果存入缓存,供post_recording端点读取 cache.set(f"transcript_{recording_sid}", transcription, ex=300) # 5分钟过期 return "", 200
内容的提问来源于stack exchange,提问作者mattkosze
相关产品推荐
相关产品推荐

