Twilio Streams外呼通话中DTMF按键传输问题求助
外呼场景下Twilio Streams通过WebSocket传输DTMF的问题解决
问题分析
你当前的两种实现方式都没命中外呼时通过WebSocket发送信令级DTMF的核心需求:
- 第一段Twiml里的
dtmfDetection="true"是用来接收通话中对方发来的DTMF,并非发送DTMF的配置; - 第二段用
<Play digits>是播放按键音的音频媒体流,本质是模拟按键声音,不是标准的RFC 2833信令DTMF,多数IVR系统只识别信令级的DTMF,所以会出现按键无效的情况。
正确解决方案
方案1:通过Twilio REST API发送DTMF(非实时触发场景)
如果不需要通过WebSocket实时控制,可直接调用Twilio Calls API发送信令级DTMF:
from twilio.rest import Client # 替换为你的Twilio账号信息 account_sid = '你的Account SID' auth_token = '你的Auth Token' client = Client(account_sid, auth_token) # 向指定通话发送DTMF call = client.calls('目标通话的Call SID').update( dtmf_digits='123#', # 支持0-9、*、# dtmf_method='POST' )
方案2:通过WebSocket Media Stream发送信令级DTMF(实时控制场景)
如果需要通过WebSocket实时触发DTMF发送,需在WebSocket连接建立后,向Twilio发送特定格式的JSON指令:
- 确保Stream配置为双向模式(你已设置
mode="duplex",符合要求); - 当需要发送DTMF时,向Twilio推送以下格式的WebSocket消息:
{ "event": "send_dtmf", "digits": "123#", "duration_ms": 200, // 按键持续时长,可选,默认200ms "gap_ms": 300 // 按键间隔,可选,默认300ms }
补充:外呼Twiml的正确流程
外呼时,先通过Twiml建立WebSocket流连接,之后即可通过WebSocket发送send_dtmf事件传输DTMF,你的第一段Twiml配置是正确的,可直接使用:
<Response> <Connect> <Stream url='wss://你的域名/websocket路由'> <Parameter name="mode" value="duplex" /> <Parameter name="dtmfDetection" value="true" /> </Stream> </Connect> </Response>
常见排查点
- 确认WebSocket连接为双向duplex模式,单向模式无法发送DTMF;
- 检查发送的JSON格式是否合规:
event字段必须为send_dtmf,digits仅允许0-9、*、#字符; - 若对方IVR仍不识别,可调整
duration_ms和gap_ms参数,比如将按键时长延长至300ms; - 确保WebSocket服务能正常接收Twilio消息,且发送的指令未被防火墙或代理拦截。
内容的提问来源于stack exchange,提问作者Shivam Sharma
相关产品推荐
相关产品推荐

