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收發(fā)采用的是不同的端口,所以可能會造成收到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事件壓入到該隊列。
然后供需要使用的地方從隊列中彈出

FS的inband解析DTMF方式
FS處理inband的DTMF需要調用兩個APP。
start_dtmf/stop_dtmf。
在dialplan里直接調用這兩個APP即可。網上大部分的教程是通過dialplan的。
如果使用命令,在發(fā)起呼叫的時候可以通過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的方式的話請注意幾點:
- 存在準確性問題。 可能不是100%準確
- 如果使用非g711a/u編碼,可能要不再適用。一些高壓縮比的編碼可能導致FS的inband處理不了。
- mod_spandsp默認是在FS源碼里的,也會默認編譯。但是不會默認加載。如果適用,請執(zhí)行加載。
如何將獲取的DTMF轉給別的呼叫腿
存在一些場景,在一條腿上獲取到了dtmf事件,但是需要轉給其他腿。特別是在bridge的時候。
FS在bridge的時候,默認會處理這種情況。

它會把腿1的dtmf都傳給腿2.
如果不想傳的話,設置參數bridge_filter_dtmf。