前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用FreeSWITCH检测声音文件中的DTMF信息

使用FreeSWITCH检测声音文件中的DTMF信息

作者头像
Seven Du
发布2020-12-21 15:23:02
2.3K0
发布2020-12-21 15:23:02
举报

今天,有网友问到一个问题——使用什么工具检测录音文件中的DTMF信息。其实FreeSWITCH本身就具备检测DTMF的功能,简单配置一下,写几个脚本就可以了。

先简单说一下DTMF,DTMF是Double Tone Multiple Frequency的缩写,即双音多频。在电话通话中,通过两个不同的频率的组合来传递按键信息,如题图中所显示的,1209和697两种频率的组合就代表1,其它依此类推。

在模拟电话以及传统的PSTN中,DTMF与声音数据是混在一起的,因为它们根本没法分开。在VoIP中常常使用DTMF2833或SIP INFO来传输DTMF,但那不是我们今天要讲的内容。

由于DTMF与声音都混在话路中,在录音时就也一块将DTMF信息录在了录音文件中,如果想从录音文件中提取这些DTMF信息,就需要对声音文件进行分析,也就是今天我们要解决的问题。

我们有了FreeSWITCH,当然不需要去找别的工具,下面我们就来看一看怎么做。

为了做一次完整的实验,我们先得有个录音文件。首先把SIP电话设成使用inband方式发送DTMF,以便能够录到DTMF信息,具体的设置方式因不同的话机(或软电话)而已,我们就不多说了。然后,使用如下方法我们可以得到一个录音文件:

代码语言:javascript
复制
freeswitch> originate user/1008 &record(/tmp/dtmf.wav)

上面使用originate命令呼叫1008,被叫接听后,开始录音。记得接听后要按几个键啊。在本次实验中,我按了1234,并挂机。

挂机后找个工具播放一下dtmf.wav,便能听到嘀嘀的按键音,虽然每个按键的声音不一样,但我们的耳朵认不出来,还得借助软件。

我们昨天刚讲了Lua,今天正好进一步再来一个例子,因而我们写了一个Lua脚本来检测DTMF,命名为dtmf.lua,内容如下:

代码语言:javascript
复制
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」)

其中,我们设了一个回调函数 onInputCBF,当检测到DTMF时便进行回调,在日志中打印相关的DTMF信息。

session:answer() 对Channel进行应答 session:execute()执行一个App,这里我们执行了start_dtmf以启动对inband类型的DTMF的检测 session:setInputCallbck()安装一个回调函数,在检测到DTMF时便执行该回调函数,就是我们上面写的那个onInputCBF session:streamFile() 一行只是播放一个无限长的声音文件,防止挂机

通过该Lua脚本,当有电话呼入时,我们将来电路由到该脚本,便可以实时检测来电中的DTMF了。但是在这里我们有一个问题,那就是我们要检测的是录音文件里面的,它不是一路电话,即不是一个Channel。

当然,这也难不住我们,既然我们有FreeSWITCH,那我们可以弄两个FreeSWITCH实例,从一个中呼叫另一个,在其中一个执行playback以播放声音文件,另一个执行上面的Lua脚本检测,问题不就解决了?

是的,但我们还有更简单的解决办法。

在FreeSWITCH中,不管是播放声音文件还是检测DTMF都需要一个Channel,在没有实际Channel的情况下,我们就可以生成一个假的Channel。对于这一点,FreeSWITCH早就帮我们想到了,那就是loopback Interface。它其实也是一个Endpoint,通过下面的命令生成一个Channel,并执行我们的Lua脚本:

代码语言:javascript
复制
freeswitch> originate loopback/dtmf &lua(dtmf.lua)

其中,loopback/ 后面的dtmf是被叫号码,当一个Channel产生后,该Channel的一端(一头)会进入Dialplan查找路由,另一头则执行 lua App,即执行我们的Lua脚本。关于loopback我们就不多解释了,我们只需要知道它在查找Dialplan时需要在Dialplan中让它能找到,因而,我们在默认的Dialplan(default.xml)中加入以下内容:

代码语言:javascript
复制
<extension name="dtmf">
    <condition field="destination_number" expression="dtmf">
    <action application="answer" data=""/>
    <action application="playback" data="/tmp/dtmf.wav"/>
    </condition>
</extension>

上述Dialplan会匹配被叫号码dtmf,然后应答,然后播放一个声音文件,就是我们刚才录的那一个。

在Channel的另一头执行我们的Lua脚本,就可以检测DTMF了,笔者测试时,日志输出如下:

代码语言:javascript
复制
[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

帅不帅?

当然,以上我们的Lua脚本比较简单,通过增加一些语句,你也可以比较精确的打印DTMF在录音文件中的时间等信息,这些,自己练习一下吧。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeSWITCH中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档