1.问题描述
使用如下的命令进行呼叫:originate user/9988001 9988002
在主叫接通后,会接着呼被叫,但是被叫振铃后,主叫没有任何回铃音。
直到被叫接听,主叫才能听到声音。
2.问题分析
180抓包如下:
呼叫命令:originate user/9988001 9988002
通过抓包可以发现,被叫开始振铃时,会回发180,但是FreeSWITCH收到180后并没有转给主叫,因为此时主叫已经处于answer状态,不可能再接收180.
所以FreeSWITCH直接就忽略了该180,直接导致的情况是主叫听不到任何回铃音。
183抓包如下:
呼叫命令:originate user/9988002 1865200306x
通过抓包可以发现,FreeSWITCH可以将183转给主叫,所以主叫在呼叫的时候,可以听到回铃音。
也就是说,FreeSWITCH在主叫已接听的情况下,转发183,不转发180。
那180的问题该如何解决呢?
尝试过在主叫方设置instant_ringback=true,还是不可以让主叫产生回铃音。猜测即使发过去,主叫方也会自动忽略掉180,因为主叫本身已经处于接听状态。
3.解决方案
目前能想到的解决办法是在被叫接听之前,手工向主叫播放回铃音。
3.1 增加lua脚本handle_ring.lua
脚本内容如下:
local api=freeswitch.API();
function getUUID(num)
local uuid;
local res=api:executeString("show channels like "..num.." as xml")
if res then
_,_,uuid = string.find(res,"<uuid>(.-)<%/uuid>")
end
return uuid;
end
--main function
do
local num = argv[1];
local uuid = getUUID(num);
if uuid then
freeswitch.consoleLog("debug", argv[0] .. ":>>>>start to play early media to caller {" .. num .. "}\n")
api:executeString("uuid_broadcast " .. uuid .. " ringback.wav aleg");
api:executeString("uuid_setvar ringback_for_caller true");
end
end
3.2 增加脚本event.lua
该脚本用于订阅CHANNEL_ANSWER和CHANNEL_HANGUP事件,在收到该事件后,调用下面的函数取消回铃音的播放:
--检查主叫通道上面是否正在播放回铃音,如果是的话,则需要停止
function stopRingBackMedia(evt, isHangup)
--只有被叫通道变量中含有variable_originator
local callerUUID = evt:getHeader("variable_originator");
if callerUUID then
freeswitch.consoleLog("debug", "=====>caller uuid:" .. callerUUID .. "\n");
local hasRingbackForCaller = api:executeString("uuid_getvar " .. callerUUID .. " ringback_for_caller") or "";
freeswitch.consoleLog("debug", "=====>variable_ringback_for_caller:" .. hasRingbackForCaller .. "\n");
if hasRingbackForCaller and string.len(hasRingbackForCaller)>0 then
freeswitch.consoleLog("debug", "=====>caller has autogenerated ringback, need to stop\n");
--api:executeString("uuid_break " .. callerUUID .. " all");
api:executeString("uuid_fileman " .. callerUUID .. " stop");
end
end
end
3.3 修改呼叫命令
修改后的呼叫命令如下所示:
originate {nolocal:api_on_ring='lua handle_ring.lua 9988001',export_vars='nolocal:api_on_ring'}user/9988001 9988002
这里稍微解释下{}里面的用法,使用nolocal:和export_vars实现了拨号方案中export的效果,也就是说将api_on_ring属性设置到被叫通道上。
在被叫收到180后,调用handle_ring.lua脚本。
4.其他问题
4.1 若主叫设置自动接听参数sip_auto_answer会导致挂断延迟
如果是需要主叫自动接听,按照上面的思路,应该使用如下的命令:
originate [sip_auto_answer='true',execute_on_originate='unset::sip_h_call-info']user/8924002 &bridge([api_on_ring='lua handle_ring.lua 8924002']user/9988002
但是会出现下面的问题,正常通话后,被叫挂断,主叫会仍处于通话中,直到二三十秒后才自动挂断。
正确呼叫命令为:
originate [sip_h_call-info='<sip:192.168.4.204>;answer-after=0',execute_on_originate='unset::sip_h_call-info']user/8924002 &bridge([api_on_ring='lua handle_ring.lua 8924002']user/9988002