您當(dāng)前的位置是:  首頁 > 資訊 > 文章精選 >
 首頁 > 資訊 > 文章精選 >

使用FreeSWITCH檢測聲音文件中的DTMF信息

2019-10-12 09:59:47   作者:杜金房   來源:CTI論壇   評論:0  點(diǎn)擊:


  今天,有網(wǎng)友問到一個(gè)問題——使用什么工具檢測錄音文件中的DTMF信息。其實(shí)FreeSWITCH本身就具備檢測DTMF的功能,簡單配置一下,寫幾個(gè)腳本就可以了。
  先簡單說一下DTMF,DTMF是Double Tone Multiple Frequency的縮寫,即雙音多頻。在電話通話中,通過兩個(gè)不同的頻率的組合來傳遞按鍵信息,如題圖中所顯示的,1209和697兩種頻率的組合就代表1,其它依此類推。
  在模擬電話以及傳統(tǒng)的PSTN中,DTMF與聲音數(shù)據(jù)是混在一起的,因?yàn)樗鼈兏緵]法分開。在VoIP中常常使用DTMF2833或SIP INFO來傳輸DTMF,但那不是我們今天要講的內(nèi)容。
  由于DTMF與聲音都混在話路中,在錄音時(shí)就也一塊將DTMF信息錄在了錄音文件中,如果想從錄音文件中提取這些DTMF信息,就需要對聲音文件進(jìn)行分析,也就是今天我們要解決的問題。
  我們有了FreeSWITCH,當(dāng)然不需要去找別的工具,下面我們就來看一看怎么做。
  為了做一次完整的實(shí)驗(yàn),我們先得有個(gè)錄音文件。首先把SIP電話設(shè)成使用inband方式發(fā)送DTMF,以便能夠錄到DTMF信息,具體的設(shè)置方式因不同的話機(jī)(或軟電話)而已,我們就不多說了。然后,使用如下方法我們可以得到一個(gè)錄音文件:
  freeswitch> originate user/1008 &record(/tmp/dtmf.wav)
  上面使用originate命令呼叫1008,被叫接聽后,開始錄音。記得接聽后要按幾個(gè)鍵啊。在本次實(shí)驗(yàn)中,我按了1234,并掛機(jī)。
  掛機(jī)后找個(gè)工具播放一下dtmf.wav,便能聽到嘀嘀的按鍵音,雖然每個(gè)按鍵的聲音不一樣,但我們的耳朵認(rèn)不出來,還得借助軟件。
  我們昨天剛講了Lua,今天正好進(jìn)一步再來一個(gè)例子,因而我們寫了一個(gè)Lua腳本來檢測DTMF,命名為dtmf.lua,內(nèi)容如下:
  function onInputCBF(s, type, obj, arg)
  if (type == "dtmf") then
  freeswitch.consoleLog("INFO", "Got DTMF: "  obj.digit  " Duration: "  obj.duration  "\n")
  end
  return ''
  end
  session:answer()
  session:execute("start_dtmf", "")
  session:setInputCallback('onInputCBF', '')
  session:streamFile("local_stream://moh」)
  其中,我們設(shè)了一個(gè)回調(diào)函數(shù) onInputCBF,當(dāng)檢測到DTMF時(shí)便進(jìn)行回調(diào),在日志中打印相關(guān)的DTMF信息。
  session:answer() 對Channel進(jìn)行應(yīng)答 session:execute()執(zhí)行一個(gè)App,這里我們執(zhí)行了start_dtmf以啟動(dòng)對inband類型的DTMF的檢測 session:setInputCallbck()安裝一個(gè)回調(diào)函數(shù),在檢測到DTMF時(shí)便執(zhí)行該回調(diào)函數(shù),就是我們上面寫的那個(gè)onInputCBF session:streamFile() 一行只是播放一個(gè)無限長的聲音文件,防止掛機(jī)
  通過該Lua腳本,當(dāng)有電話呼入時(shí),我們將來電路由到該腳本,便可以實(shí)時(shí)檢測來電中的DTMF了。但是在這里我們有一個(gè)問題,那就是我們要檢測的是錄音文件里面的,它不是一路電話,即不是一個(gè)Channel。
  當(dāng)然,這也難不住我們,既然我們有FreeSWITCH,那我們可以弄兩個(gè)FreeSWITCH實(shí)例,從一個(gè)中呼叫另一個(gè),在其中一個(gè)執(zhí)行playback以播放聲音文件,另一個(gè)執(zhí)行上面的Lua腳本檢測,問題不就解決了?
  是的,但我們還有更簡單的解決辦法。
  在FreeSWITCH中,不管是播放聲音文件還是檢測DTMF都需要一個(gè)Channel,在沒有實(shí)際Channel的情況下,我們就可以生成一個(gè)假的Channel。對于這一點(diǎn),F(xiàn)reeSWITCH早就幫我們想到了,那就是loopback Interface。它其實(shí)也是一個(gè)Endpoint,通過下面的命令生成一個(gè)Channel,并執(zhí)行我們的Lua腳本:
  freeswitch> originate loopback/dtmf &lua(dtmf.lua)
  其中,loopback/ 后面的dtmf是被叫號碼,當(dāng)一個(gè)Channel產(chǎn)生后,該Channel的一端(一頭)會(huì)進(jìn)入Dialplan查找路由,另一頭則執(zhí)行 lua App,即執(zhí)行我們的Lua腳本。關(guān)于loopback我們就不多解釋了,我們只需要知道它在查找Dialplan時(shí)需要在Dialplan中讓它能找到,因而,我們在默認(rèn)的Dialplan(default.xml)中加入以下內(nèi)容:
  •  
  •  
  上述Dialplan會(huì)匹配被叫號碼dtmf,然后應(yīng)答,然后播放一個(gè)聲音文件,就是我們剛才錄的那一個(gè)。
  在Channel的另一頭執(zhí)行我們的Lua腳本,就可以檢測DTMF了,筆者測試時(shí),日志輸出如下:
  • [INFO] switch_cpp.cpp:1291 Got DTMF: 1 Duration: 1120
  • [INFO] switch_cpp.cpp:1291 Got DTMF: 2 Duration: 1120
  • [INFO] switch_cpp.cpp:1291 Got DTMF: 3 Duration: 1120
  • [INFO] switch_cpp.cpp:1291 Got DTMF: 4 Duration: 1120
  帥不帥?
  當(dāng)然,以上我們的Lua腳本比較簡單,通過增加一些語句,你也可以比較精確的打印DTMF在錄音文件中的時(shí)間等信息,這些,自己練習(xí)一下吧。
  廣告時(shí)間:
  本文收錄于《FreeSWITCH 實(shí)例解析》中,感興趣的小伙伴可以點(diǎn)擊鏈接購買商品。
  現(xiàn)在加入FreeSWITCH VIP知識星球即可獲取全部『FreeSWITCH系列』電子書。
  VIP星球:
  2019年最新一期FreeSWITCH培訓(xùn)(北京站)以及第八屆FreeSWITCH開發(fā)者沙龍正在火熱報(bào)名中,現(xiàn)在報(bào)名還可享受八折優(yōu)惠,歡迎點(diǎn)擊『閱讀原文』了解詳情。
  同時(shí)歡迎贊助商及講師加入我們本次的FreeSWITCH開發(fā)者沙龍。
【免責(zé)聲明】本文僅代表作者本人觀點(diǎn),與CTI論壇無關(guān)。CTI論壇對文中陳述、觀點(diǎn)判斷保持中立,不對所包含內(nèi)容的準(zhǔn)確性、可靠性或完整性提供任何明示或暗示的保證。請讀者僅作參考,并請自行承擔(dān)全部責(zé)任。

相關(guān)閱讀:

專題

CTI論壇會(huì)員企業(yè)