FreeSWITCH 中的 DTMF 按键采集

1. FreeSWITCH 检测 DTMF 的方式

DTMF(Double Tone Multiple Frequency,双音多频)本质上是由高频音和低频音的两个正弦波合成的音频信号,不过随着技术发展,已经引申指代为电话通话过程中按键信息传输的一种方式。在 SIP 通话中,传输按键信息的方法较多,大致分为以下三种

1.1 RFC2833

RFC2833 是 FreeSWITCH 默认开启的 DTMF 检测配置,这种方式实际是由 RTP 协议中特殊的 Payload Type(按照惯例值 101)telepone-event 来标识 RFC2833 数据包,用最后一个 end 标志为 1 的 RFC2833 数据包表示 DTMF 传输结束,以文本形式直接传输按键值。一轮 DTMF 经常会多次按键输入多个数字,这样就会对应多个 RTP 数据包,在 RFC2833 模式下这些 RTP 包的时间戳相同,据此可以将多个按键值聚合作为一轮 DTMF 按键采集的最终值

在 FreeSWITCH 日志中,如果存在 RTP RECV DTMF 关键字,则按键值是通过 telepone-event 标识直接从 RTP 包中取出来的文本数据

使用方式
  1. 使用 play_and_get_digits APP,向 FreeSWITCH 下发采集按键的指令
  2. 通过 esl 订阅 CHANNEL_EXECUTE_COMPLETE 事件,在该事件监听的处理逻辑判断执行的 Application 为 play_and_get_digits,再从对应的变量中取得按键值

1.2 INBAND

INBAND 为带内检测方式,这种模式下按键值以音频信号表示,封装在 RTP 包中与普通的 RTP 语音包一起传输,检测的唯一方法是实时提取所有 RTP 包音频数据进行频谱分析,得到高频音和低频音的频率然后查表确认对应的按键值。由于 RTP 音频数据解码有一定的 CPU 消耗,不推荐使用这种方式

在 FreeSWITCH 日志中,如果存在 DTMF DETECTED 关键字,则按键值是使用带内检测从音频信号里分析出来的

使用方式
  1. 在需要使用的拨号计划中增加如下配置,需注意如果 start_dtmf 与 ring_ready 一起使用,需确保首先调用 ring_ready
  <action application="set" data="dtmf_type=inband"/>
  <action name="start_dtmf"/>
  1. 通过 esl 订阅 DTMF 事件,在该事件监听的处理逻辑中拿到用户按键信息

1.3 SIP INFO

SIP INFO 为带外检测方式,直接通过 SIP 信令通道传输 DTMF 数据。这种方式比 RFC2833 更有效率,但由于 SIP 信令和 RTP 收发采用的是不同的端口,所以可能会造成收到 DTMF 和实际的声音不同步的问题

如果媒体协商时 SDP 里没有 telepone-event 则表明 SIP 设备不支持 RFC2833 模式传输按键信息,此时 FreeSWITCH 会默认改用 SIP INFO 模式传输 DTMF,产生如下日志:

No 2833 in SDP.  Disable 2833 dtmf and switch to INFO
使用方式

在需要使用的拨号计划中增加如下配置

 <action application="set" data="dtmf_type=info"/>

2. DTMF 数据重复问题

2.1 start_dtmf 的问题

在使用 start_dtmf APP 采用带内检测的方式采集 DTMF 按键时,如果运营商同时用 INBANDRFC2833 两种方式传输了 DTMF 信号,则在 FreeSWITCH 中会出现按键数据重复的问题,因为 FreeSWITCH 默认开启的 RFC2833 也会解析获取按键信息。这种情况有两种解决方法:

  1. 要求运营商只采用一种方式发送 DTMF
  2. 关闭 FreeSWITCH 的 INBAND 的检测方式,不使用 start_dtmf

2.3 运营商传输问题

在某些情况下,运营商确实存在重复传输 DTMF 信号的问题。这种情况需要使用 wireshark 抓包分析 RTP 流,导出音频流后使用相关工具分析频率,对照 DTMF 频率表确认是否存在重复发送问题,网上资料很多在此不做赘述

猜你喜欢

转载自blog.csdn.net/weixin_45505313/article/details/129753593