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

Twilio语音机器人如何在TwiML Say播报完成后触发Media Stream的WebSocket服务

解决方案

你遇到的问题由两个核心原因导致,按以下步骤修复即可:

1. 先修复基础错误

你的代码里存在两处低级拼写错误,会直接导致Twilio收到错误响应无法执行后续指令:

  • 呼叫端点里你定义的响应变量是voice_respond,返回时错误写为voice_response
  • say方法的voice参数有效值是woman,你错误写为women

2. 解决呼叫状态错误问题

ringing是呼叫尚未接通的临时状态,只有当呼叫正式接通后,状态才会变为in-progress,此时才能执行修改通话、启动媒体流等操作。
把你呼叫端点的状态判断逻辑修改为:

@app.route("/twilio_call", methods=['POST'])
def voice(request):
    """Respond to incoming phone calls with a greet message"""
    call_status = request.form.get("CallStatus")
    # 仅在通话正式接通后返回业务TwiML
    if call_status == "in-progress":
       voice_response = VoiceResponse()
       # 给say添加action属性,播报完成后Twilio会自动请求该地址
       voice_response.say("hello! how can I help!", voice='woman', action='/start_stream', method='POST')
       return response.text(str(voice_response), content_type="text/xml")
    # 其他状态返回空响应即可
    return Response(status=200)

3. 实现问候语播报完成后自动启动媒体流

你之前将Say和Stream放在同一份TwiML里无法生效,是因为<Start><Stream>指令会被Twilio优先异步执行,和Say的播放时序冲突。
新增一个专门启动媒体流的端点,等问候语播报完成后Twilio会自动调用该端点,此时返回带Stream的TwiML即可:

@app.route("/start_stream", methods=['POST'])
def start_stream(request):
    voice_response = VoiceResponse()
    start = Start()
    start.stream(url='wss://<NGROK_IP>.ngrok.io/webhooks/twilio_voice/media')
    voice_response.append(start)
    # 可以在这里加一个空的<Pause>保证流连接稳定,也可以不加
    voice_response.pause(length=1)
    return response.text(str(voice_response), content_type="text/xml")

4. 修复修改通话的报错

你之前调用client.calls.update报错,是因为调用时机过早,呼叫还没进入in-progress状态。
你可以等媒体流WebSocket端点收到第一次event为media的消息后,再调用修改通话的接口,此时通话状态一定是可修改的:

@app.websockets('/media')
def transcribe_media(request, ws):
    client = Client(ACCOUNT_SID, AUTH_TOKEN)
    while True:
        message = ws.recv()
        if message is None:
            continue
        data = json.loads(message)
        if data['event'] == "media":
            # 此处发送数据到Google STT获取转写结果
            msg_text = "你的转写后响应内容"
            # 拿到转写结果后再修改通话,此时状态一定是in-progress
            call_sid = data['start']['callSid']
            call = client.calls(call_sid).update(
                twiml=f'<Response><Say voice="woman" language="de-DE">{msg_text}</Say></Response>'
            )

内容的提问来源于stack exchange,提问作者busy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:27:01