

烟台小樱桃网络科技有限公司致力于中国开源社区的发展,专注于FreeSWITCH和相关开源语音技术的技术推广和实践。为了为广大国内用户提供更权威更细节的技术分享,公司不仅出版了关于FreeSWITCH的图书,并且尽可能通过在线方式提供了多种技术解读。
本文档涵盖FreeSWITCH的媒体处理架构和编解码器协商机制。它详细介绍了 FreeSWITCH 在呼叫建立和桥接操作期间如何选择、处理和转码音频/视频编解码器,希望以较短的篇幅全面介绍编码协商的机制和配置示例。
我们为前期技术实战操作用户和第三方开发爱好者提供了一站式封装的开源完整电话系统,大家可以下载小樱桃的开源IPPBX实现电话互联互通:
开源轻量 IP-PBX 新选择|CherryPBX 正式公开构建

有关特定音频编解码器实现的信息,请参阅音频编解码器。有关 SIP 特定的转码配置,请参阅小樱桃和FreeSWITCH中文社区官方技术资料,配置和实用程序。
FreeSWITCH 实现了一个复杂的编解码器协商系统,支持两种主要模式:早期协商(立即编解码器选择)和晚期协商(延迟编解码器选择)。该系统评估呼叫支路之间的编解码器兼容性,并在必要时应用转码。
媒体处理
协商引擎
通道变量
SIP 配置文件配置
inbound-codec-prefs
outbound-codec-prefs
inbound-late-negotiation
disable-transcoding
codec_string
absolute_codec_string
inherit_codec
ep_codec_string
media_mix_inbound_outbound_codecs
早期协商过程
晚期协商过程
编解码器匹配算法
SDP 处理
转码引擎
代理媒体处理器
媒体桥接
早期协商(默认行为)在呼叫到达时立即执行编解码器选择,甚至在拨号计划处理之前。该算法优先考虑入站 SDP 编解码器顺序而非 FreeSWITCH 偏好设置。
A-leg INVITE with SDP
Check against inbound-codec-prefs
Select first matching codec
A-leg codec negotiated
Process dialplan
Generate B-leg INVITE
Reorder outbound-codec-prefswith A-leg codec first
B-leg codec selection
Bridge with potential transcoding
No codec match
Call failure
晚期协商需要设置 inbound-late-negotiation=true,并将 A-leg 编解码器选择延迟到拨号计划执行之后,从而实现更复杂的编解码器匹配策略。
Yes
No
A-leg INVITE with SDP
Defer codec negotiation
Process dialplan
inherit_codec=true?
Negotiate B-leg first
Normal negotiation
B-leg codec selected
Set A-leg to same codec
No transcoding needed
Potential transcoding
参数 | 模式 | 功能 |
|---|---|---|
inbound-codec-prefs | 两者 | 定义可接受的入站编解码器 |
outbound-codec-prefs | 两者 | 定义首选出站编解码器顺序 |
inbound-late-negotiation | 晚期 | 启用晚期协商模式 |
disable-transcoding | 早期 | 强制出站编解码器与入站匹配 |
变量 | 范围 | 目的 |
|---|---|---|
codec_string | 拨号计划 | 覆盖 outbound-codec-prefs |
absolute_codec_string | 拨号计划 | 强制精确编解码器列表,忽略配置文件 |
inherit_codec | 晚期协商 | 强制 A-leg 继承 B-leg 编解码器 |
ep_codec_string | 晚期协商 | 只读,包含呼叫方提供的编解码器 |
media_mix_inbound_outbound_codecs | 转码 | 启用混合编解码器桥接 |
媒体处理实现
媒体处理
处理决策
编解码器兼容性检查
Yes
No
Yes
No
Yes
No
Yes
No
A-leg Codec
B-leg Codec
Compare Codecs
Same Codec?
disable-transcoding=true?
media_mix_inbound_outbound_codecs=true?
proxy_media=true?
Direct Media Bridge
Transcoding Process
Proxy Media Passthrough
Call Failure
SDP(会话描述协议)处理编解码器属性解析、ptime 验证和媒体格式协商。
SDP 输出生成
编解码器评估
SDP 输入处理
Inconsistent ptime
Incoming SDP
Parse m=audio line
Extract codec attributes
Validate ptime consistency
Match against profile prefs
Apply channel variable overrides
Reorder codec preferences
Build outbound SDP offer
Add codec-specific attributes
Finalize SDP structure
Log ptime warningDisable ptime attribute
代理媒体模式绕过 FreeSWITCH 的媒体处理,需要对编解码器协商进行特殊处理。在代理媒体模式下,必须先调用 answer 应用程序才能进行编解码器协商。
answer() executed
Direct media attempt
SDP processing enabled
Successful negotiation
Call termination
Call completion
ProxyMediaEnabled
AnswerCalled
CodecNegFailed
CodecNegotiation
MediaPassthrough
FreeSWITCH 支持通过 switch_r_sdp 通道变量进行运行时 SDP 修改,从而实现自定义编解码器优先级排序和属性修改。
<!-- 示例:优先考虑 G.729 编解码器 -->
<condition field="${switch_r_sdp}" expression="/(.*)(m=audio \d+ RTP\/AVP)(?=[ \d]+18|18[ \d]+)([ \d]*)(.*)/s">
<action application="set" data="codec_mangle= 18"/>
<action application="set" data="switch_r_sdp=$1$2${codec_mangle} 101$4"/>
</condition><!-- 启用混合编解码器桥接 -->
<action application="bridge" data="{media_mix_inbound_outbound_codecs=true}sofia/gateway/provider/number"/>
<!-- 强制特定编解码器列表 -->
<action application="bridge" data="{absolute_codec_string='PCMA,PCMU'}sofia/internal/destination"/>
<!-- 在 A-leg 上继承 B-leg 编解码器 -->
<action application="set" data="inherit_codec=true"/>
<action application="bridge" data="sofia/external/destination"/>