mod_da2使用说明

介绍

mod_da2是一个FreeSWITCH的定制模块,在呼叫前设置通道变量execute_on_media=start_da2,就可以在呼叫的时候启动空号识别。

下载

http://www.dingdingtong.cn/mod_da2_last.rar

安装

假设 fs安装目录是 /usr/local/freeswitch/

da2.conf.xml copy到 fs安装目录/conf/autoload_configs/da2.conf.xml
da2.json copy到 fs安装目录/conf/da2.json
libda2.so copy到 fs安装目录/lib/libda2.so
mod_da2.so copy到 fs安装目录/mod/mod_da2.so

fs安装目录/conf/autoload_configs/modules.conf.xml 末尾( 之前)加入

fs_cli 执行 da2 show ,如果输出ready:ok ,就是和daserver连接正确。

测试

fs_cli 测试

bgapi originate {execute_on_media=start_da2}sofia/external/da1@47.97.5.205:16080 &park
bgapi originate sofia/external/da1@47.97.5.205:16080 &da2

有的线路,比如IMS,需要fs先发包,才可以接收到早期媒体,可以这样:
bgapi originate {execute_on_media=start_da2}sofia/external/da1@47.97.5.205:16080 wait_for_answer_da,park inline
bgapi originate sofia/external/da1@47.97.5.205:16080 &da2(1)

通过API启动
originate {origination_uuid=myuuid,api_on_media=’uuid_start_da2 myuuid’}sofia/external/da2@ddrj.com:16060 wait_for_answer_da,park inline
fs1.8部分版本存在bug需要修改sofia.c代码才可以,特别加了一个API,避开这个BUG。
originate {origination_uuid=myuuid,api_on_media=’bgapi uuid_start_da2 myuuid’}sofia/external/da2@ddrj.com:16060 wait_for_answer_da,park inline

自定义检测参数覆盖da2.conf.xml配置
bgapi originate {execute_on_media=start_da2,da2_param_stoptone=’sample busy’,da2_param_autohangup=true,da2_param_ignoresamples=’abc’,da2_param_answerautosotp=true,da2_param_maxdetecttime=30}sofia/external/da1@47.97.5.205:16080 wait_for_answer_da,park inline

先呼叫手机,然后呼叫分机
originate {origination_caller_id_number=主叫号码,execute_on_media=start_da2}sofia/external/vad1@ddrj.com:16080 ‘m:^:wait_for_answer_da:60000^bridge:{origination_caller_id_number=主叫号码,origination_caller_id_name=主叫用户}user/1000’ inline

dialplan测试

 <extension name="da">
<condition field="destination_number" expression="^(\d*)$">
<action application="export" data="nolocal:execute_on_media=start_da2"/>
<action application="bridge" data="sofia/external/da1@47.97.5.205:16080"/>
</condition>
</extension>

自动外呼程序注意

很多自动外呼程序 会加 ignore_early_media=true 来等待应答后再转入dialplan。
加了这个变量就无法识别了。
需要用 wait_for_answer_da 代替这个变量
比如 originate {execute_on_pre_answer=start_da2}sofia/external/da1@47.97.5.205:16080 wait_for_answer_da,transfer:’dest XML public’ inline

wait_for_answer_da支持设置等待超时,比如60秒不应答就挂机
originate {execute_on_pre_answer=start_da2}sofia/external/da1@47.97.5.205:16080 wait_for_answer_da:60000,transfer:’dest XML public’ inline

配置

da2.conf.xml,设置空号识别模块参数。

<configuration name="da2.conf" description="Dial tone analysis">
<settings>

<!-- libda2配置文件路径 -->

<!-- <param name="configurefilename" value="/etc/da2.json"/> -->
<!-- <param name="configurefilename" value="da2.json"/> -->

<!-- libda2日志文件路径 -->
<!-- <param name="logfilename" value="/var/log/da2.log"/> -->
<!-- <param name="logfilename" value="da2.log"/> -->


<!--
检测到什么信号停止检测
all busy ringback colorringback prompt sample silence 450hz
可以通过通道变量 da2_param_stoptone 覆盖这个的配置
-->
<param name="stoptone" value="sample busy"/>

<!-- 识别到 stoptone 包含的信号 自动挂断通话,默认true
可以通过通道变量 da2_param_autohangup 覆盖这个的配置
-->
<param name="autohangup" value="true"/>

<!-- 指定检测原因时挂断通话。 检测停止原因列表 all stoptone detecttime_timeout bus_close answer bug_add_fail break func_exit da1
和 autohangup 的区别,autohangup为真的时候 只有检测到stoptone包含的信号才挂断。
可以通过通道变量 da2_param_hangupcondition 覆盖这个的配置
-->
<param name="hangupcondition" value=""/>


<!-- 忽略那些的样本 用别名(alias) 英文的。多个用逗号隔开
可以通过通道变量 da2_param_ignoresamples 覆盖这个的配置
-->

<param name="ignoresamples" value=""/>




<!-- 不设置recordpath 就不会录音 -->
<!-- <param name="recordpath" value="da_record"/> -->

<!-- 把识别结果加到录音文件名 -->
<!-- <param name="recordrename" value="true"/> -->

<!--
电话接通后停止识别
可以通过通道变量 da2_param_answerautostop 覆盖这个的配置
-->
<param name="answerautostop" value="true"/>

<!--
最大检测时间 单位(秒)
可以通过通道变量 da2_param_maxdetecttime 覆盖这个的配置
-->
<param name="maxdetecttime" value="60"/>

<!--
最大分析时间,有声音后开始计算 单位(秒)
可以通过通道变量 da2_param_maxanalysistime 覆盖这个的配置
-->
<param name="maxanalysistime" value="60"/>

<!--
最大静音时间 单位(秒)
可以通过通道变量 da2_param_maxsilencetime 覆盖这个的配置
-->
<param name="maxsilencetime" value="30"/>


<!--
应答之后最大分析时间 单位(秒)
可以通过通道变量 da2_param_answer_after_maxanalysistime 覆盖这个的配置
answerautosotp设置为false,这个变量才生效
-->
<param name="answer_after_maxanalysistime" value="10"/>



<!--
提示音和彩铃最大分析时间 单位(秒)
可以通过通道变量 da2_param_ptd_maxanalysistime 覆盖这个的配置
-->
<param name="ptd_maxanalysistime" value="10"/>


</settings>


<hangupcause>
<!--


ID 状态 别名 描述
2 关机 power off 关机
3 空号 does not exist 空号
4 停机 out of service 停机
5 正在通话中 hold on 正在通话中
6 用户拒接 not convenient 用户拒接
7 无法接通 is not reachable 无法接通
8 暂停服务 not in service 暂停服务
9 用户正忙 busy now 用户正忙
10 拨号方式不正确 not a local number 拨号方式不正确
11 呼入限制 barring of incoming 呼入限制
12 来电提醒 call reminder 各类秘书服务
13 呼叫转移失败 forwarded 呼叫转移失败
14 网络忙 line is busy 网络忙
15 无人接听 not answer 无人接听
16 欠费 defaulting 欠费
17 无法接听 cannot be connected 无法接听
18 改号 number change 改号
19 线路故障 line fault 线路不能呼出,比如SIM卡欠费
20 稍后再拨 redial later 各种稍后再拨提示

根据识别结果发送不同的SIP挂断代码

<param name="2" value="432"/>
<param name="3" value="433"/>
<param name="4" value="434"/>
<param name="5" value="435"/>
<param name="6" value="436"/>
<param name="7" value="437"/>
<param name="8" value="438"/>
<param name="9" value="439"/>
<param name="10" value="440"/>
<param name="11" value="441"/>
<param name="12" value="442"/>
<param name="13" value="443"/>
<param name="14" value="444"/>
<param name="15" value="445"/>
<param name="16" value="446"/>
<param name="17" value="447"/>
<param name="18" value="448"/>
<param name="19" value="449"/>
<param name="20" value="450"/>

-->
</hangupcause>

<!--
通过 info 发送识别结果
header 设置info 消息头
compatibility 根据FS版本设置 40 或者 41


<sendinfo>
<param name="header" value="X-Genesys-Reason"/>
<param name="compatibility" value="41"/>
</sendinfo>
-->

</configuration>

da2.json 设置云服务器连接参数。

{
    "da" : 
    {
        "connect" : 
        {
            "addr" : "da2.ddrj.com",
            "port" : 9977,
            "reConnectInterval" : 15000,
            "timer" : 5000
        },
        "key" : "aaa"
    }
}

ESL获取识别结果

订阅esl 事件

java
setEventSubscriptions(EventFormat.PLAIN, “CHANNEL_HANGUP_COMPLETE CUSTOM da2”);

fs_cli测试 可以 /event CHANNEL_HANGUP_COMPLETE CUSTOM da2 订阅 事件

电话挂断获取检测结果

订阅 CHANNEL_HANGUP_COMPLETE,CHANNEL_HANGUPCOMPLETE 事件的通道变量,前面需要加 variable

检测停止后会设置以下通道变量

  • da2_finish_cause 停止原因
  • da2_all_tone 所以检测到信号类型位与结合 (详细见da2_tone说明)
  • da2_last_tone 检测到信号类型 (详细见da2_tone说明)
  • da2_last_sample_category 检测到样本ID (详细见category说明)
  • da2_last_sample_correction 检测的修正结果详细见category说明)
  • da2_result 根据以上信息设置一个方便读取的检测结果
  • da2_finish_cause 停止原因说明

    • unknown 未知
    • stoptone 检测到配置文件指定的信号,而停止的
    • detecttime_timeout 检测超时
    • answer 通话应答了
    • bus_close [start_da2]通话给挂断了 (就是还没检测到结果通话就给挂掉了,一般可能是呼叫失败)
    • bug_add_fail [start_da2]获取媒体失败
    • break [da2 app]执行了break
    • func_exit [da2 app]函数位置原因退出了
  • da2_tone
    如果停止原因是 stoptone,可以获取通道变量da2_tone,继续获取具体信号类型。

    • da2_tone 数字值说明
      • DA_TONE_BUSYTONE = 0x01 //忙音
      • DA_TONE_RINGBACKTONE = 0x02 //回铃
      • DA_TONE_COLORRINGBACKTONE = 0x04 //彩铃(音乐)
      • DA_TONE_PROMPTTONE = 0x08 //提示音(说话声)
      • DA_TONE_SAMPLE = 0x10 //匹配到样本
      • DA_TONE_SILENCE = 0x20 //静音
      • DA_TONE_450HZ = 0x40 //450hz的嘟音
    • da2_tone 文本值说明:
      • sample 匹配到样本
      • busy 忙音
      • ringback 回铃音
      • colorringback彩铃(音乐)
      • prompt 提示音(说话声)
      • silence 静音
      • 450hz 450hz的嘟音(如果持续的嘟声符合回铃或者忙音,也会有busy或者ringback)(比如忙音(嘟0.35秒,静音0.35秒),回铃音(嘟1秒,静音4秒))
      • unkown 未知的值
  • da2_all_tone 把所有检测到的信号类型(da2_tone)位与的方式结合 - da2_last_tone 最后检测到的信号类型看da2_tone说明。
  • da2_last_sample_category 最后匹配到的样本ID
  • da2_last_sample_correction 如果最后的检测结果是通话中和用户正忙,并且之前检测到回铃或者彩铃,出现检测结果的呼叫时间大于45秒,设置是为 not answer(无人接听),小于 45秒 设置为 not convenient(用户拒接)

如果有a-leg,会在a-leg通道设置以下通道变量

  • bridge_da2_finish_cause
  • bridge_da2_all_tone
  • bridge_da2_last_tone
  • bridge_da2_last_sample_category
  • bridge_da2_last_sample_correction

实时获取检测结果 订阅

Event-Subclass: da2 Event-Name: CUSTOM

  • 事件和通道变量内容
    • Event-Subclass da2
    • da2_point_begin
    • da2_point_end
    • da2_tone
    • da2_sample_uniqueid
    • da2_sample_name
    • da2_sample_alias
    • da2_sample_brief
    • da2_sample_detail
    • da2_sample_language
    • da2_sample_category
  • 具体含义

    • da2_point_begin: 识别到结果的开始位置
    • da2_point_end: 识别到结果的结束位置
    • tone: 识别到的信号音类型,具体看 da2_tone 说明
    • 如果 tone是sample 才会设置以下变量
    • uniqueid: 样本ID
    • name: 样本名字,具体看 category。
    • alias: 样本别名
    • brief: 样本文本简介
    • detail: 样本详细内容
    • language: 样本语言类型 可能是 普通话|方言|英语 | zh | en 等
    • source: 样本来源
    • number: 样本来源的号码
    • recognize: 算法引擎
    • accuracy: 识别结果的准确性, LOOSE(不准),INACCURACY(一般),ACCURACY(准确),只有ACCURACY(准确)的才会通知ESL和执行挂机

    • category: 样本分类

      2 	关机 		power off 		关机
      3 空号 does not exis 空号
      4 停机 out of service 停机 (欠费很久给停机了)
      5 正在通话中 hold on 正在通话中,大部分交换机用户拒接,无应答,也是返回正在通话中。
      6 用户拒接 not convenient 用户拒接,可能用户直接挂断吧,很少见,大部分交换机都是直接返回通话中。
      7 无法接通 is not reachable 无法接通,可能手机没信号
      8 暂停服务 not in service 暂停服务,刚欠费,给限制呼入了。
      9 用户正忙 busy now 用户正忙 ,没开通来电等待时,用户已经在通话中。
      10 拨号方式不正确 not a local number 拨号方式不正确,不符合线路拨号要求,一般是外地手机要加0.
      11 呼入限制 barring of incoming 呼入限制 可能是没开通语音功能,或者欠费,暂停服务等。
      12 来电提醒 call reminder 各类秘书服务,和各类来电提醒,语音信箱,语音留言。
      13 呼叫转移失败 forwarded 呼叫转移失败 ,被叫开通了呼叫转移,转移的目标手机呼叫失败。
      14 网络忙 line is busy 网络忙 很少见,一般是线路局端出故障了。
      15 无人接听 not answer 无人接听,很少见。
      16 欠费 defaulting 欠费 ,被叫欠费了,也可能是主叫欠费了,样本库没区分那么细致。
      17 无法接听 cannot be connected 无法接听,很少见。和无人接听,不清楚2个提示音的具体区别。
      18 改号 number change 改号,有的地方有改号提示,就是用户换号了。
      19 线路故障 line fault 线路不能呼出,比如SIM卡欠费
      20 稍后再拨 redial later 各种稍后再拨提示,一般是用户忙,通话中,关机等之后的提示音(这个会导致没法细分,可以在da2.conf.xml,配置忽略这个分类)完整的提示一般是,你拨打的用户正忙,请稍后在拨,或者你拨打的正在通话中,请稍后在拨

常见问题

空号识别,本质是语音识别,所有识别结果,都是通过分析声音获取的,和信令无关。

比如识别结果是空号,那么这个号码是不是真的是空号呢,这个不能保证的,只能保证,系统呼叫这个号码听到的声音和空号样本匹配上了。

比如系统检测到是空号,用自己手机呼叫这个号码是正常的,因为外呼的线路呼叫接续出了问题也可能提示空号的。

有以下几个可能

1 线路问题,就是 系统使用的线路有问题,把正常的号码播放了空号的提示音。 (大部分是这样的问题)
2 运营商问题, 就是运营商有时候会把正常的号码播放空号的声音,重新呼叫一次又正常了,这样的也属于线路问题(外呼发起的运营商和被叫号码归属地运营商接续出问题)。 (小概率可能出现)
3 样本库问题,就是系统把一个其他样本标志成空号。 (非常小概率,默认样本库基本上没这样的问题)

怎么排查问题,录音, 1 fs系统去录音未接通之前的声音,2 da2.conf.xml 配置去打开录音 3 通过命令动态开录音 da2 record /tmp (第三个参数录音目录,可以自己设置),

听一下录音,就可以知道是 线路问题,还是样本库问题。

fs_cli 里面执行

显示状态,可以判断和daserver连接是否正常。看输出的 ready是否1,limit是否正确。
da2 show

打开录音
da2 record /tmp

关闭录音
da2 record

界面展示问题

如果信令结果是呼叫应答的,分类到应答
如果呼叫结果是没应答的
先根据 da2_finish_cause 来判断,如果 da2_finish_cause的结果是 stoptone,那么界面显示 da2_tone,如果da2_tone等于sample,那么显示da2_sample_name。
2.13版本开始添加了变量da2_result,就是这样规则来设置的。

da2_finish_cause的其他检测原因为了更友好的显示,建议如下显示
bus_close 如果呼叫持续时间小于30秒,分类到呼叫失败,如果大于30秒,分类到未识别
detecttime_timeout 如果da2_last_tone有数据,就根据 da2_last_tone 来显示,如果没有,就分类到未识别。
answer 分类到应答
其他值,不应该出现,直接归类到其他。