You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Twilio Action参数请求录音时出现500错误(11200&12200)排查

问题原因
  1. 触发时机差异:
    • 使用action="/handle_audio"时,Twilio会在录制动作结束的瞬间立即调用该端点,但此时录音文件还处于Twilio后台处理流程中,并未完全生成并对外可访问,直接请求RecordingUrl自然返回404。
    • recording_status_callback="/handle_audio"则是在录音完全处理完成、文件就绪后才触发,此时RecordingUrl有效,能正常下载音频。
  2. 错误对应:
    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:02:04