FreeSWITCH基本应用
1. 启动&关闭FreeSWITCH
前台启动:/usr/local/freeswitch/bin/freeswitch 关闭前台FS:shutdown
后台启动:/usr/local/freeswitch/bin/freeswitch -nc 关闭后台FS:/usr/local/freeswitch/bin/freeswitch -stop
以上每次启动都需要输入一个很长的一个路径,方便起见可以把[freeswitch]和[fs_cli]加入到[usr/bin],执行命令如下:
ln -sf /usr/local/freeswitch/bin/freeswitch /usr/bin
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/bin
2. 查看FreeSWITCH上已注册话机的信息
查看命令:show registrations
3. 话机向FreeSWITCH注册流程
1> 如果注册号码为:1000~1019这20个账号,该20个账号的默认密码为1234,所以只需要知道FS所在服务器的IP地址(默认端口号为5060),既可进行注册。
2> 如果注册帐号为1000~1019以外的账号,比如8888或者9999。则手册如下:
(1) 在/usr/local/freeswitch/conf/directory/default目录下,将1000.xml拷贝为你需要注册的账号,如8888.xml,编辑8888.xml并将该文件里所有的1000都替换为8888。修改之后就可以通过话机注册8888账号了,然后你会发现该账号的话机只能进行拨打电话不能接听电话,这是因为还需要修改FS的拨号规则。
(2) 修改拨号规则:修改/usr/local/freeswitch/conf/dialplan/default.xml,将呼叫规则的正则表达式expression="^(10[01][0-9])$"修改为:expression="^(10[01][0-9]|8888|9999)$"。修改之后加载配置文件即可拨打与呼叫8888账号了。
4. FreeSWITCH配置网关
如果要实现FS内部已注册账号分别拨打,这个是不需要网关的。但是,你想通过FS内部已注册账号拨打未注册的外线(如手机号码),此时需要FS与外部网关连接,FS引入网关来处理外线拨打功能。(本人是通过使用公司的网关进行操作的)
FS配置网关需要:用户名,密码以及网关服务器IP地址,FS配置网关如下:
1> 添加网关配置:如添加[123456]的网关:/usr/local/freeswitch/conf/sip_profiles/external/123456.xml,配置内容如下
<include> <gateway name="123456"> <param name="username" value="123456"/> <param name="password" value="888888"/> <param name="realm" value="192.168.*.*"/> <param name="expire-seconds" value="3600"/> <param name="register" value="false"/> <param name="retry-seconds" value="60"/> <param name="caller-id-in-from" value="false"/> <param name="supress-cng" value="false"/> <param name="extension-in-contact" value="false"/> </gateway> </include>
保存以上代码,并执行命令:sofia profile external restart 对sip profile进行重启。重启后,可以查看网关注册状态,命令为:sofia status。正常情况下网关注册成功,现在虽然注册了网关信息,但是FS内部账号还是不能拨打外线,还需要配置第二部操作。
2> FreeSWITCH内线通过网关呼叫外线
追加网关呼叫配置文件:/usr/local/freeswitch/conf/dialplan/default/123456.xml
<include> <extension name="extension-call"> <condition field="destination_number" expression="^(\d{8,12})$"> <action application="bridge" data="sofia/gateway/123456/$1"/> </condition> </extension> </include>
保存文件后,FS执行 reloadxml 重新加载配置文件,这样你的内线就能正常拨打符合8到12位的外线了,比如能正常拨打手机号码。然而此时仅仅是能拨打外线,并不能接听外线,要接听外线还需要执行第三部。
备注:在这一步中本人遇到了一个坑,那就是虽然按上面的保存了配置文件也重新加载了,但是还是不能拨打11位数的手机号码。这是因为在123456.xml同级目录下有个[01_example.com.xml]文件,该文件里有个配置规则正好是11位数的,所以,我配置的11位手机号码没有走到我配置的文件里来,而是被[01_example.com.xml]里的配置规则优先匹配了,此时需要注释[01_example.com.xml]的部分代码,或是删除该文件亦可。
3> 接收网关发来的呼叫
对于那些未经认证的呼叫,FS认为是不安全的,即使是网关发送过来的呼叫。FS把这类呼叫路由到public dialplan context中。编辑网关发来的呼叫配置:/usr/local/freeswitch/conf/dialplan/public/123456.xml
<?xml version="1.0" encoding="utf-8"?> <include> <extension name="123456"> <condition field="destination_number" expression="^(123456)$"> <action application="set" data="hangup_after_bridge=true"/> <action application="export" data="airgo_trunk_number=123456"/> <action application="transfer" data="8000 XML default"/> </condition> </extension> </include>
当外来用户通过网关呼叫FS时,FS将来电转移到8000账号。
5. 修改FreeSWITCH默认注册端口号
FS默认监听端口号是:5060,然而如果FS部署在公网上,则很容易遭到别人恶意攻击与破解,所以建议修改FS默认的注册端口号。修改端口号:编辑配置文件freeswitch/conf/vars.xml
1 <!-- Internal SIP Profile --> 2 <X-PRE-PROCESS cmd="set" data="internal_auth_calls=true"/> 3 <X-PRE-PROCESS cmd="set" data="internal_sip_port=5060"/> 4 <X-PRE-PROCESS cmd="set" data="internal_tls_port=5061"/> 5 <X-PRE-PROCESS cmd="set" data="internal_ssl_enable=false"/> 6 <!-- 可以看到freeswitch的监听端口为5060 如果想监听其他的端口则把5060 改为你要监听的端口号 -->
6. 修改FreeSWITCH默认认证密码
FS默认认证密码为:1234,可以根据需要进行修改。编辑配置文件:freeswitch/conf/vars.xml,找到:<X-PRE-PROCESS cmd="set" data="default_password=1234"/> ,将默认的“1234”修改之。
7. 通话录音
FS可以对通话进行录音,编辑配置文件:vi freeswitch/conf/dialplan/default.xml,对分机进行如下设置:
1 <extension name="Local_Extension"> 2 <condition field="destination_number" expression="^(10[01][0-9]|9999)$"> 3 <action application="export" data="dialed_extension=$1"/> 4 <!-- add for recording begin --> 5 <action application="record_session" data="$${base_dir}/recordings/${strftime(%Y)}/${strftime(%m)}/${strftime(%d)}/${caller_id_number}_${strftime(%H-%M-%S)}.wav"/> 6 <!-- add recording end -->
录音结果如下:
其实,在这里会联想到把录音的配置设置为一个函数,所以在任何地方需要配置录音,只需要设置:<action application="export" data="allow_recording=true"/>即可。以下是通过lua进行录音设置。
8.为FreeSWITCH添加G729编解码模块
FS默认的G729模块是不支持转码只支持透传,G729编码在FS中Linux平台上有Licence解决方案,购买一路需要10美元,其中包括一个编码器和一个解码器。作为学习和实验,所以在网上找了一个破解版来实现FS的G729转码功能。
实验环境:Centos6.5 + FreeSWITCH:1.6.0~64bit
获取模块源代码:mod_g729
详细操作:
(1)备份fs源码中的mod_g729。
cd freeswitch源码目录/src/mod/codecs
mv mod_9729 mod_g729_bak
(2)解压刚下载的G729模块源码。
unzip 1712150417.zip
mv mod_g729 freeswitch源码目录/src/mod/codecs
(3)编译G729模块
cd freeswitch源码目录/src/mod/codecs/mod_g729
make
(4)安装
cd freeswitch源码目录
make install
(5)配置
FS添加G729编解码:
vi /usr/local/freeswitch/conf/vars.xml
<X-PRE-PROCESS cmd="set"data="global_codec_prefs=G729,OPUS,G722,PCMU,PCMA,VP8"/>
<X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=G729,OPUS,G722,PCMU,PCMA,VP8"/>
FS启动时自动加载G729模块:
vi /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml
<!-- Codec Interfaces -->
<load module="mod_g729"/> //这一行不能被注释
重新加载sofia配置和G729模块:
sofia profile internal restart //重新加载sofia internal配置
reload mod_g729 //重新加载mod_g729模块
(6)测试
9.代接
(1)全局代接
1 <extension name="global-intercept"> 2 <condition field="destination_number" expression="^886$"> 3 <action application="answer"/> 4 <action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/global)}"/> 5 <action application="sleep" data="2000"/> 6 </condition> 7 </extension>
(2)同组代接
1 <extension name="group-intercept"> 2 <condition field="destination_number" expression="^\*8$"> 3 <action application="answer"/> 4 <action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/${callgroup})}"/> 5 <action application="sleep" data="2000"/> 6 </condition> 7 </extension>
(3)指定分机代接
1 <extension name="intercept-ext"> 2 <condition field="destination_number" expression="^\*\*(\d+)$"> 3 <action application="answer"/> 4 <action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/$1)}"/> 5 <action application="sleep" data="2000"/> 6 </condition> 7 </extension>
10.转接
1 <action application="bind_meta_app" data="1 b s execute_extension::dx XML features"/> *1 忙转 2 <action application="bind_meta_app" data="3 b s execute_extension::cf XML features"/> 3 <action application="bind_meta_app" data="4 b s execute_extension::att_xfer XML features"/> *4 协商转
11.定时呼叫
有时想定呼叫一个电话。关于定时任务,可以使用Linux自动的crontable,但是我用golang语言自己写了个定时任务,来调用lua脚本进行呼叫。
1 // golang 主要代码 2 func main() { 3 c := cron.New() 4 spec := "0 * * * * *" // 每分钟执行一次 5 c.AddFunc(spec, call) 6 c.Start() 7 select {} 8 } 9 10 func call() { 11 cmd := exec.Command("/usr/local/freeswitch/bin/fs_cli", "-x", "luarun /home/tom/call.lua") 12 if err := cmd.Run(); err != nil { 13 fmt.Println(err) 14 } 15 } 16 17 // lua脚本。其中gw代表的是外呼所用的网关,187代表的是需要呼叫的号码 18 session = freeswitch.Session("{origination_caller_id_number=9999,origination_caller_id_name=9999}user/9999"); 19 if session:ready() then 20 session2 = freeswitch.Session("sofia/gateway/gw/187********"); 21 if session2:ready() then 22 freeswitch.bridge(session, session2) 23 session:hangup(); 24 end 25 end 26 27 最终实现每分钟呼叫一次187的号码。
12.FreeSWITCH设置中文Phrase
FS默认是没有中文的语音文件配置的,如果需要让FS支持中文语音则需要手动配置。
(1)添加中文配置文件。
cd /usr/local/freeswitch/conf/lang //进入lang目录
cp -R en zh //从en目录复制生成zh目录
cd zh //进入zh目录
mv en.xml zh.xml //将en.xml改为zh.xml
vi zh.xml //编辑zh.xml,将language一行修改如下
<language name="zh" say-module="zh" sound-prefix="$${sounds_dir}/zh/cn/callie" tts-engine="cepstral" tts-voice="callie">
(2)加载中文配置文件
vi /usr/local/freeswitch/conf/freeswitch.xml //编辑配置文件
<section name="languages" description="Language Management">
<X-PRE-PROCESS cmd="include" data="lang/zh/*.xml"/> //添加该行
(3)修改FS默认语音为中文
vi /usr/local/freeswitch/conf/vars.xml //编辑配置文件
<X-PRE-PROCESS cmd="set" data="sound_prefix=$${sounds_dir}/zh/cn/callie"/>
(4)Say接口加载中文模块
Say接口支持各种语言,如需支持中文语言,则需要编译源码价值mod_say_zh模块
make mod_say_zh-install
freeswitch>reload mod_say_zh
为了让FS启动时自动加载该模块,编辑配置文件conf/autoload_configs/modules.conf.xml,添加:<load module="mod_say_zh"/>
参考资料:http://www.cnblogs.com/zxqdlenovo/p/4031060.html
12.fs_cli连接FreeSWITCH时报错
报错内容:[ERROR] fs_cli.c:1610 main() Error Connecting [Socket Connection Error]
错误原因:FreeSWITCH 没有启动或 mod_event_socket 没有正确加载,请检查TCP端口8021端口是否处于监听状态或被其它进程占用(netstat -anp | grep 8021)。我的解决如下:
1 vi /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml 2 <configuration name="event_socket.conf" description="Socket Client"> 3 <settings> 4 <param name="nat-map" value="false"/> 5 <!--<param name="listen-ip" value="::"/> 将该行注释并添加下行--> 6 <param name="listen-ip" value="0.0.0.0"/> 7 <param name="listen-port" value="8021"/> 8 <param name="password" value="ClueCon"/> 9 <!--<param name="apply-inbound-acl" value="loopback.auto"/>--> 10 <!--<param name="stop-on-bind-error" value="true"/>--> 11 </settings> 12 </configuration>
13.ivr按键无效时需设置按键类型
<action application="set" data="dtmf_type=inband"/>
<action application="start_dtmf" data=""/>
14.条件运算符(cond <expr> ? <true val> :<false val>)
1 <condition field="${cond(${my_var} > 12 ? YES : NO)}" expression="^YES$"> 2 <action application="log" data="INFO ${my_var} is indeed greater than 12"/> 3 <anti-action application="log" data="INFO ${my_var} is not greater than 12"/> 4 </condition>
15.接通后再录音
需求:录音时不要将前置媒体录制进去.
用法:<action application="set" data="media_bug_answer_req=true"/>
16.录音文件的路径权限如何修改为755
由于录音文件的路径权限(文件夹权限)默认是750权限,所以通过http获取不到录音文件,需要把录音文件的路径权限改为755。
解决方案:修改源码重新编译(如果有多台服务器的freeswitch需要解决该问题,不需要单独编译,只需在一台服务器上编译,然后把编译后得到的libfreeswitch.so.1.0.0文件拷贝到对应路径(/usr/local/freeswitch/lib/libfreeswitch.so.1.0.0)即可
1 cd /usr/local/src/freeswitch/src 2 vi switch_ivr_async.c 3 # 在函数 switch_ivr_record_session() 4 # 修改前为(L2529):if (switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { 5 # 修改后如下(把 SWITCH_DEFAULT_DIR_PERMS 修改为 SWITCH_FPROT_OS_DEFAULT): 6 if (switch_dir_make_recursive(path, SWITCH_FPROT_OS_DEFAULT, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { 7 # 保存&退出 8 cd /usr/local/src/freeswitch 9 make 10 make install
17.如何关闭写freeswitch.log
由于freeswitch默认会加载mod_logfile模块,日积月累会写很多log文件导致磁盘空间不足,默认日志路径是:/usr/local/freeswitch/log/freeswitch.log。所以可以关闭mod_logfile模块。
1 # 取消启动自加载mod_logfile 2 vim /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml 注释掉 <load module="mod_logfile"/> ,然后重启freeswitch即可。如果不想启动freeswitch,则可在控制台执行:unload mod_logfile
18.freeswitch支持G729编码
(1). 设置全局的G729编码
1 vim /usr/local/freeswitch/conf/vars.xml 2 # 以下设置需要的编码 3 <X-PRE-PROCESS cmd="set" data="global_codec_prefs=PCMU,PCMA,G729"/> 4 <X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=PCMU,PCMA,G729"/>
(2).自动外呼程序指定使用G729编码
autodialer_task 表 originate_variables 字段设置 {absolute_codec_string=g729}
(3).替换 freeswitch/mod 文件夹下的:mod_g729.so、mod_g729.la 文件( 下载 提取密码: rcli)。
19.呼入接收带内(inband)按键
<extension name="ivr_demo">
<condition field="destination_number" expression="5000">
<action application="answer"/>
<action application="start_dtmf"/>
<action application="ivr" data="demo_ivr"/>
</condition>
</extension>
20.顺振&共振
场景1:分机顺振(若要改为共振仅需将“|”改为“,”即可)内部分机,测试效果好使,能满足预期。
<extension name="顺振">
<condition field="destination_number" expression="^(41001)$">
<action application="set" data="continue_on_timeout=true"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="bridge" data="[leg_timeout=15]user/8000|[leg_timeout=15]user/8001"/>
</condition>
</extension>
场景2:外呼顺振,即通过网关先拨打手机号1,若手机号未接通则再拨手机号2。测试结果不如人意,因为手机号拨打的话会出现即使未接通都会听到“您拨打的电话无人接通,请稍后再拨”
<extension name="test_outbound">
<condition field="destination_number" expression="^(56789)$">
<action application="set" data="continue_on_timeout=true"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="set" data="continue_on_fail=NORMAL_TEMPORARY_FAILURE,TIMEOUT,NO_ROUTE_DESTINATION,USER_BUSY,NO_ANSWER,NO_USER_RESPONSE,CALL_REJECTED,OUTGOING_CALL_BARRED,ALLOTTED_TIMEOUT"/>
<action application="set" data="effective_caller_id_name=${outbound_caller_id_name}"/>
<action application="set" data="effective_caller_id_number=${outbound_caller_id_number}"/>
<action application="bridge" data="[leg_timeout=15]sofia/gateway/gw/176x|[leg_timeout=15]sofia/gateway/gw/159x"/>
</condition>
</extension>