团队博客
用 XSwitch 检查 WAV 文件里面的 DTMF
韩小仿 2024-03
用 XSwitch 检查 WAV 文件里面的 DTMF
跟着我做下面操作:
浏览器打开 XSwitch,登录之后,新建一条路由,参数如下:
- 名称: 检查带内 dtmf
- 被叫号码: dtmfdetect
- 最大号长: 10
- 呼叫源: 分机(context-1)
- 目的地类型: 系统
在文本里面输入下面的内容:
answer set min_dup_digit_spacing_ms=60 spandsp_start_dtmf set playback_terminators=none playback silence_stream://-1,1400
接着找到 ”维护/终端“,输入下面命令:
originate loopback/dtmfdetect/context-1 &playback(tone_stream://1234567890)
下面是部分执行的日志:
EXECUTE [depth=0] loopback/dtmfdetect-b answer() 2025-06-25 14:15:05.926618 99.70% [NOTICE] mod_dptools.c:1412 Channel [loopback/dtmfdetect-b] has been answered 2025-06-25 14:15:05.927614 99.70% [DEBUG] switch_channel.c:4024 (loopback/dtmfdetect-b) Callstate Change RINGING -> ACTIVE EXECUTE [depth=0] loopback/dtmfdetect-b spandsp_start_dtmf() 2025-06-25 14:15:05.927614 99.70% [DEBUG] switch_core_media_bug.c:1003 Attaching BUG spandsp_dtmf_detect to loopback/dtmfdetect EXECUTE [depth=0] loopback/dtmfdetect-b set(playback_terminators=none) 2025-06-25 14:15:05.927614 99.70% [DEBUG] mod_dptools.c:1677 SET loopback/dtmfdetect-b [playback_terminators]=[none] EXECUTE [depth=0] loopback/dtmfdetect-b playback(silence_stream://-1,1400) 2025-06-25 14:15:05.928617 99.70% [DEBUG] switch_ivr_play_say.c:1561 Codec Activated L16@8000hz 1 channels 20ms 2025-06-25 14:15:05.952599 99.70% [DEBUG] billing.c:475 billing task started id=13 2025-06-25 14:15:05.970633 99.70% [DEBUG] switch_core_io.c:448 Setting BUG Codec L16:100 2025-06-25 14:15:05.990630 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [1] 2025-06-25 14:15:05.990630 99.70% [INFO] switch_channel.c:539 RECV DTMF 1:2000 2025-06-25 14:15:05.990630 99.70% [DEBUG] mod_dptools.c:2378 Digit 1 2025-06-25 14:15:06.190604 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [1], duration = 204 ms 2025-06-25 14:15:06.270605 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [2] 2025-06-25 14:15:06.270605 99.70% [INFO] switch_channel.c:539 RECV DTMF 2:2000 2025-06-25 14:15:06.270605 99.70% [DEBUG] mod_dptools.c:2378 Digit 2 2025-06-25 14:15:06.510605 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [2], duration = 242 ms 2025-06-25 14:15:06.570605 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [3] 2025-06-25 14:15:06.570605 99.70% [INFO] switch_channel.c:539 RECV DTMF 3:2000 2025-06-25 14:15:06.570605 99.70% [DEBUG] mod_dptools.c:2378 Digit 3 2025-06-25 14:15:06.810639 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [3], duration = 242 ms 2025-06-25 14:15:06.890638 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [4] 2025-06-25 14:15:06.890638 99.70% [INFO] switch_channel.c:539 RECV DTMF 4:2000 2025-06-25 14:15:06.890638 99.70% [DEBUG] mod_dptools.c:2378 Digit 4 2025-06-25 14:15:07.130639 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [4], duration = 242 ms 2025-06-25 14:15:07.190636 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [5] 2025-06-25 14:15:07.190636 99.70% [INFO] switch_channel.c:539 RECV DTMF 5:2000 2025-06-25 14:15:07.190636 99.70% [DEBUG] mod_dptools.c:2378 Digit 5 2025-06-25 14:15:07.430639 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [5], duration = 242 ms 2025-06-25 14:15:07.510640 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [6] 2025-06-25 14:15:07.510640 99.70% [INFO] switch_channel.c:539 RECV DTMF 6:2000 2025-06-25 14:15:07.510640 99.70% [DEBUG] mod_dptools.c:2378 Digit 6 2025-06-25 14:15:07.750636 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [6], duration = 242 ms 2025-06-25 14:15:07.810640 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [7] 2025-06-25 14:15:07.810640 99.70% [INFO] switch_channel.c:539 RECV DTMF 7:2000 2025-06-25 14:15:07.810640 99.70% [DEBUG] mod_dptools.c:2378 Digit 7 2025-06-25 14:15:08.070639 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [7], duration = 242 ms 2025-06-25 14:15:08.130639 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [8] 2025-06-25 14:15:08.130639 99.70% [INFO] switch_channel.c:539 RECV DTMF 8:2000 2025-06-25 14:15:08.130639 99.70% [DEBUG] mod_dptools.c:2378 Digit 8 2025-06-25 14:15:08.390637 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [8], duration = 242 ms 2025-06-25 14:15:08.450638 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [9] 2025-06-25 14:15:08.450638 99.70% [INFO] switch_channel.c:539 RECV DTMF 9:2000 2025-06-25 14:15:08.450638 99.70% [DEBUG] mod_dptools.c:2378 Digit 9 2025-06-25 14:15:08.690637 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [9], duration = 242 ms 2025-06-25 14:15:08.770639 99.70% [DEBUG] mod_spandsp_dsp.c:405 DTMF BEGIN DETECTED: [0] 2025-06-25 14:15:08.770639 99.70% [INFO] switch_channel.c:539 RECV DTMF 0:2000 2025-06-25 14:15:08.770639 99.70% [DEBUG] mod_dptools.c:2378 Digit 0 2025-06-25 14:15:09.010638 99.70% [DEBUG] mod_spandsp_dsp.c:417 DTMF END DETECTED: [0], duration = 242 ms
拨号字符串 loopback/dtmfdetect/context-1 分成了三部分,其中 loopback 是端点,dtmfdetect 是被叫号码,context-1 是呼叫源。
loopback 比较特别,自动创建两个相互连通的通道,其中呼出的通道在呼出成功后播放带内 DTMF 1234567890,呼入的通道执行创建好的路由: 应答,设置通道变量,执行 spandsp_start_dtmf(检查带内 DTMF),循环播放静音。
上面的日志可以看到,呼出通道发送的是 1234567890,呼入通道接收到全部 DTMF,不多也不少。
在上面的路由里面可以再增加一个通道变量 set dtmf_verbose=true,识别的过程可以在日志里面更清楚地体现出来。
一般来说,VoIP 倾向于用 RFC2833 来传递 DTMF,但如果 XSwitch 跟落地网关对接,网关一侧按了键,但 XSwitch 收不到,那怎么办呢? 可以在路由里面选择录音,通话结束后把录音文件复制到 /tmp 目录,比如文件名为 test.wav,再执行下面的 API:
originate loopback/dtmfdetect/context-1 &playback(/tmp/test.wav)
观察日志就可以知道是否真的有带内 DTMF 送过来。
此外,如果二个按键间隔时间比较长,可以用 start_dtmf 来代替 spandsp_start_dtmf,但如果间隔时间比较短,建议使用 spandsp_start_dtmf。 一般来说,min_dup_digit_spacing_ms 建议设置为 60 毫秒,这个参数来自经验,设置过大过小可能就不合适,导致收到重复的按键或者丢失按键。