IVR按键输入的一个核心能力的处理DTMF。

Freeswitch自身有处理DTMF的能力。

DTMF的处理机制

FS共支持三种DTMF处理方式,分别为inband、rfc2833、sipinfo

1.1.INBAND
INBAND为带内检测方式,而且与普通的RTP语音包混在一起传送。
1.2.RFC2833
RFC2833即识别一种特殊RTP报文,报文格式如下,其中Event ID表示按键值,同一个DTMF按键通常会对应多个RTP包,这些RTP数据包的时间戳均相同,此可以作为识别同一个按键的判断依据,最后一包RTP数据包的end标志置1表示DTMF数据结束。
另外,很多SIP UA默认的TeleponeEvent都为101,但可以人为修改,这时要求在进行RFC2833 DTMF检测之前需事先获取SDP协商的TeleponeEvent参数;
1.3.SIPINFO
SIPINFO为带外检测方式,通过SIP信令通道传输DTMF数据。这种方式甚至比RFC2833更有效。但是由于SIP信令和RTP收发采用的是不同的端口,所以可能会造成收到DTMF和实际的声音不同步。

配置

配置文件conf/sip_profile/internal.xml和external.xml
internal和external是单独配置的,关于DTMF都有相同的配置项
<param name="dtmf-type" value="rfc2833"/>
这个值默认好像是注释的。注释的默认为inband。
value的值可以是none或者rfc2833。

使用rfc2833的情况下,FS只需要解析RTP流程中的event事件即可。
不过使用rfc2833要求线路或者对端支持这种方式,如果不支持,可以使用inband方式交给FS处理。

某些语音网关可以处理inband的DTMF,然后生成rfc2833rtp event。但是一些设备会存在准确率的问题

FS处理DTMF的简单机制

FS内部使用了一个队列dtmf_inqueue存储了dtmf结构体。 所有从rtp中获取的dtmf事件压入到该队列。
然后供需要使用的地方从队列中弹出

 
dtmf_inqueue

FS的inband解析DTMF方式

FS处理inband的DTMF需要调用两个APP。
start_dtmf/stop_dtmf。
在dialplan里直接调用这两个APP即可。网上大部分的教程是通过dialplan的。
如果使用命令,在发起呼叫的时候可以通过originate的参数带上。如下

originate {execute_on_answer=start_dtmf,origination_uuid=.....

start_dtmf/stop_dtmf是默认的mod_dptool里的,于此类似的还有一个模块mod_spandsp也提供了两个APP:spandsp_start_dtmf/spandsp_stop_dtmf
个人感觉这个效果会更好一点。

如果使用inband的方式的话请注意几点:

  1. 存在准确性问题。 可能不是100%准确
  2. 如果使用非g711a/u编码,可能要不再适用。一些高压缩比的编码可能导致FS的inband处理不了。
  3. mod_spandsp默认是在FS源码里的,也会默认编译。但是不会默认加载。如果适用,请执行加载。

如何将获取的DTMF转给别的呼叫腿

存在一些场景,在一条腿上获取到了dtmf事件,但是需要转给其他腿。特别是在bridge的时候。

FS在bridge的时候,默认会处理这种情况。

 

 

 

它会把腿1的dtmf都传给腿2.
如果不想传的话,设置参数bridge_filter_dtmf。

转自:https://www.jianshu.com/p/e86b9a85fc1c