FreeSWITCH媒体绕行

本文简要说明在我个人使用过程中涉及的一些情况,并非是完全涵盖的技术文档,仅供参考。

涉及参数

  1. bypass_media
  2. bypass_media_after_bridge
  3. bridge_early_media
  4. ignore_early_media

在diaplan中实现

在拨号计划(diaplan)中,实现方式比较简单,只需要设置bypass_media=true,之后再通过bridge的方式做sip呼叫的桥接即可。具体实现方式如下:

<extension name="to_out_opensips">
    <condition field="destination_number" expression="^((\d{11})|(\d{7,8})|(\d{4}|\d{3})(\d{7,8}))$">
        <action application="set" data="inherit_codec=true"/>
        <action application="set" data="bypass_media=true"/>
        <action application="set" data="continue_on_fail=true"/>
        <action application="set" data="originate_timeout=90"/>
        <action application="set" data="hangup_after_bridge=true"/>
        <action application="bridge" data="sofia/external/[email protected]:5060"/>
    condition>
extension>

在lua脚本中实现

所谓在lua脚本中实现,及SIP呼叫的桥接过程是在lua脚本中实现的,我们要保证在lua脚本中bridge也能做到媒体绕行。

第一步:参考在diaplan中的实现方式,在拨号计划中触发lua脚本,在lua脚本中bridge。

<extension name="to_out_opensips">
    <condition field="destination_number" expression="^((\d{11})|(\d{7,8})|(\d{4}|\d{3})(\d{7,8}))$">
        
        <action application="set" data="bypass_media=true"/>
        <action application="set" data="continue_on_fail=true"/>
        <action application="set" data="originate_timeout=90"/>
        <action application="set" data="hangup_after_bridge=true"/>
        <action application="lua" data="xsr_call.lua"/>
    condition>
extension>
-- 可以在lua脚本中做相关参数设置
-- session:execute("set","bypass_media=true")
-- session:execute("set","continue_on_fail=true")
-- session:execute("set","originate_timeout=90")
-- session:execute("set","hangup_after_bridge=true")

destination_number = 13044174782
originate_str = "sofia/external/" .. destination_number .. "@172.27.0.2:5060"
session:execute("bridge", originate_str)

第二步:如果做了如下设置,sip呼叫没有什么问题,那么就可以了,如果说在响铃阶段(early media)的时候就中断了,可以做bridge_early_media=true的设置。

<extension name="to_out_opensips">
    <condition field="destination_number" expression="^((\d{11})|(\d{7,8})|(\d{4}|\d{3})(\d{7,8}))$">
        
        
        <action application="set" data="bridge_early_media=true"/>
        <action application="set" data="bypass_media=true"/>
        <action application="set" data="continue_on_fail=true"/>
        <action application="set" data="originate_timeout=90"/>
        <action application="set" data="hangup_after_bridge=true"/>
        <action application="lua" data="xsr_call.lua"/>
    condition>
extension>

关于bypass_media_after_bridge的说明

官网文档说明:bypass_media_after_bridge

Same as bypass_media but will handle media for a call until it has reached the answered state (and has processed a few RTP frames.) At this point FreeSWITCH will use a ReInvite to take itself out of the media path. This helps reduce audio latency and take some load off FreeSWITCH. Especially useful for UACs behind Coned NAT as it gives RTP Auto-Adjust enough time to determine the correct ports to avoid one-way audio.

与bypass_media相同,但将处理呼叫的媒体,直到其达到应答状态(并已处理了一些RTP帧。)此时,FreeSWITCH将使用ReInvite将自己从媒体路径中移出。 这有助于减少音频等待时间并减轻FreeSWITCH的负担。 对于Coned NAT后面的UAC尤其有用,因为它为RTP自动调整提供了足够的时间来确定正确的端口,以避免单向音频。

简单来说,bypass_media_after_bridge即为在bridge之后做媒体绕行,中间会涉及少量媒体流的中转,并不能达到完全媒体绕行的效果。

我在使用过程中发现,使用bypass_media_after_bridge,在lua脚本中做bridge,不设置bridge_early_media=true,呼叫不会再early media的时候中断。

注意事项

设置不生效

在lua脚本中有部分做法是无法达到媒体绕行的。

第一种:

destination_number = 13044174782
originate_str = "{bypass_media=true}sofia/external/" .. destination_number .. "@172.27.0.2:5060"
-- originate_str = "[bypass_media=true]sofia/external/" .. destination_number .. "@172.27.0.2:5060"
session:execute("bridge", originate_str)

第二种:

destination_number = 13044174782
originate_str = "sofia/external/" .. destination_number .. "@172.27.0.2:5060"
session1 = freeswitch.Session(originate_str, session)

if (session1:ready()) then
    freeswitch.bridge(session, session1)
end

lua中bridge不再阻塞到hangup

媒体绕过会导致lua脚本中的bridge不在阻塞,即bridge之后的内容会在sip呼叫接通以后直接执行。如果想在挂机hangup之后再做一些操作,可通过session_in_hangup_hookapi_hangup_hook实现,实现当时如下:

<extension name="test">
    <condition field="destination_number" expression="13044174782">
        <action application="set" data="inherit_codec=true"/>
        
        <action application="set" data="bridge_early_media=true"/>
        <action application="set" data="bypass_media=true"/>
        <action application="set" data="continue_on_fail=true"/>
        <action application="set" data="originate_timeout=90"/>
        <action application="set" data="hangup_after_bridge=true"/>
        <action application="set" data="session_in_hangup_hook=true"/>
        <action application="set" data="api_hangup_hook=lua xsr_hangup.lua"/>
        <action application="export" data="nolocal:execute_on_answer=lua xsr_ring_monitor.lua ${uuid}"/>
        <action application="lua" data="xsr_bridge.lua"/>
    condition>
extension>

如果需要在api_hangup_hook触发的脚本中获取bridge之前一些参数,可以在bridge之前将需要的参数设置到信道变量中。

你可能感兴趣的:(Freeswitch)