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

动态切换Twilio TwiML的<Connect>/<Start>标签及实现可行性问询

问题解答

整体方案可行性

这个方案是可行的,但需要注意两个关键点:

  • 必须在通话处于**活跃状态(in-progress)**时调用update_async更新TwiML
  • 通话不能有正在执行的TwiML动作(比如正在播放音频、收集按键等),否则更新会失效

步骤1:获取并提取Stream URL的实现方式

根据你的TwiML配置来源,有两种常见实现路径:

场景1:TwiML存储在自己的服务器/数据库

如果初始TwiML是由你的服务生成并返回的,直接从缓存、数据库或业务逻辑中读取对应的Stream URL即可,无需额外请求Twilio API。

场景2:TwiML是Twilio控制台配置的静态内容

通过Twilio API获取号码的语音配置,再解析提取Stream URL:

  1. 获取号码的语音配置
    使用Twilio SDK获取目标号码的资源,其中包含静态TwiML的访问地址:
    # 替换为你的号码SID(PN开头)
    phone_number = await self.twilio_client.incoming_phone_numbers("PNxxxxxx").fetch_async()
    # 静态TwiML的访问URL
    twiml_url = phone_number.voice_url
    
  2. 请求并解析TwiML内容
    向twiml_url发送请求(需要用Twilio账号SID和Auth Token做Basic认证),拿到XML后用Twilio的TwiML解析库提取Stream URL:
    from twilio.twiml.voice_response import VoiceResponse, Connect, Start, Stream
    import httpx
    from requests.auth import HTTPBasicAuth
    
    # 请求Twilio获取静态TwiML
    auth = HTTPBasicAuth("你的账号SID", "你的Auth Token")
    response = httpx.get(twiml_url, auth=auth)
    xml_content = response.text
    
    # 解析XML提取Stream URL
    voice_response = VoiceResponse.from_xml(xml_content)
    stream_url = None
    
    # 查找<Connect>下的<Stream>
    for verb in voice_response:
        if isinstance(verb, Connect):
            for nested in verb:
                if isinstance(nested, Stream):
                    stream_url = nested.url
                    break
            break
    # 如果没找到,查找<Start>下的<Stream>
    if not stream_url:
        for verb in voice_response:
            if isinstance(verb, Start):
                for nested in verb:
                    if isinstance(nested, Stream):
                        stream_url = nested.url
                        break
                break
    

优化建议

既然你的Stream URL是固定的(wss://123-123-123.ngrok-free.app/ws),完全可以跳过提取步骤,直接根据参数生成目标TwiML:

# 根据参数生成对应TwiML
def generate_target_twiml(use_start: bool, stream_url: str):
    response = VoiceResponse()
    if use_start:
        start = Start()
        start.stream(url=stream_url)
        response.append(start)
    else:
        connect = Connect()
        connect.stream(url=stream_url)
        response.append(connect)
    return response

# 调用更新
target_twiml = generate_target_twiml(use_start=True, stream_url="wss://123-123-123.ngrok-free.app/ws")
await self.twilio_client.calls(self.call_sid).update_async(
    method="POST", twiml=target_twiml.to_xml()
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:23:26