FreeSWITCH 媒体处理
文档创建日期 |
2024-03-18 |
作者 |
Walter Fan |
关键词 |
FreeSWITCH, Media, Codec, RTP, Transcoding, WebRTC |
状态 |
v1.0 |
摘要 |
本章详细介绍 FreeSWITCH 中的媒体处理机制,包括音视频编解码器支持、 编解码器协商与转码、媒体代理与绕行模式、录音回放、DTMF 处理、 音频处理以及 RTP 配置与优化等核心内容。 |
概述
FreeSWITCH 是一个开源的软交换平台,其核心能力之一就是强大的媒体处理功能。 在 WebRTC 通信场景中,FreeSWITCH 常常扮演媒体服务器(Media Server)或 会话边界控制器(SBC)的角色,负责处理音视频流的接收、转发、转码和录制等任务。
FreeSWITCH 的媒体处理架构主要包含以下几个层次:
信令层(Signaling Layer): 通过 mod_sofia 模块处理 SIP 信令,完成会话的建立、 修改和拆除,其中 SDP(Session Description Protocol)协商是媒体参数确定的关键环节。
媒体层(Media Layer): 负责 RTP/RTCP 包的收发、编解码器的编解码处理、 以及各种媒体操作(如混音、录音、播放等)。
应用层(Application Layer): 提供丰富的拨号计划(Dialplan)应用, 如 bridge、record、playback、conference 等,供用户灵活编排媒体处理流程。
FreeSWITCH 的媒体引擎(Media Engine)采用模块化设计,通过加载不同的编解码器模块 (如 mod_opus、mod_av 等)来扩展其编解码能力。其内部使用 L16(线性 16 位 PCM) 作为核心音频格式,所有编解码器的输入输出都会经过 L16 的转换,这使得不同编解码器 之间的转码变得透明和统一。
+-------------------+
| Application | (bridge, record, playback, conference ...)
+-------------------+
| Media Engine | (codec encode/decode, mixing, processing)
+-------------------+
| RTP/RTCP Stack | (packet send/recv, jitter buffer, DTMF)
+-------------------+
| Network I/O | (UDP sockets, ICE, DTLS-SRTP for WebRTC)
+-------------------+
支持的音频编解码器
FreeSWITCH 支持丰富的音频编解码器,涵盖了从传统电话网络到现代 WebRTC 通信的各种需求。 以下是主要支持的音频编解码器及其特性:
编解码器 |
采样率 (Hz) |
比特率 (kbps) |
帧长 (ms) |
音质评级 |
说明 |
|---|---|---|---|---|---|
G.711 PCMU |
8000 |
64 |
20 |
中等 |
ITU-T 标准,μ-law 编码,北美和日本广泛使用 |
G.711 PCMA |
8000 |
64 |
20 |
中等 |
ITU-T 标准,A-law 编码,欧洲和国际广泛使用 |
G.722 |
16000 |
64 |
20 |
较高 |
宽带编解码器,提供 50-7000Hz 频率响应 |
Opus |
8000-48000 |
6-510 |
2.5-60 |
极高 |
WebRTC 必选编解码器,支持语音和音乐,自适应比特率 |
iLBC |
8000 |
13.3/15.2 |
30/20 |
中等 |
对丢包有良好的容错性,适合网络不稳定场景 |
GSM |
8000 |
13 |
20 |
较低 |
移动通信标准编解码器,压缩率高 |
Speex |
8000/16000/32000 |
2.15-44.2 |
20 |
中高 |
开源编解码器,已被 Opus 取代,但仍广泛部署 |
SILK |
8000-24000 |
6-40 |
20 |
较高 |
Skype 开发,适合语音通话,低延迟 |
G.711 (PCMU/PCMA)
G.711 是最基础也是兼容性最好的音频编解码器,几乎所有 VoIP 设备都支持。 PCMU(μ-law)主要在北美使用,PCMA(A-law)在欧洲和其他地区使用。 虽然比特率较高(64kbps),但由于其极低的计算复杂度,在转码场景中几乎不消耗 CPU 资源。
<!-- 在 vars.xml 中设置全局编解码器偏好 -->
<X-PRE-PROCESS cmd="set" data="global_codec_prefs=PCMU,PCMA"/>
<X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=PCMU,PCMA"/>
Opus
Opus 是 WebRTC 的必选音频编解码器,也是 FreeSWITCH 中处理 WebRTC 呼叫的关键。 通过 mod_opus 模块提供支持,它具有以下优势:
支持 8kHz 到 48kHz 的采样率,自适应切换
支持 CBR(恒定比特率)和 VBR(可变比特率)模式
内置前向纠错(FEC)机制,增强抗丢包能力
支持 DTX(不连续传输),节省带宽
<!-- opus.conf.xml 配置示例 -->
<configuration name="opus.conf">
<settings>
<param name="use-vbr" value="1"/>
<param name="use-dtx" value="1"/>
<param name="complexity" value="10"/>
<param name="packet-loss-percent" value="15"/>
<param name="keep-fec-enabled" value="1"/>
<param name="use-jb-lookahead" value="1"/>
<param name="maxaveragebitrate" value="64000"/>
<param name="maxplaybackrate" value="48000"/>
<param name="sprop-maxcapturerate" value="16000"/>
<param name="adjust-bitrate" value="1"/>
</settings>
</configuration>
支持的视频编解码器
FreeSWITCH 对视频编解码器的支持主要通过 mod_av(基于 FFmpeg/libav)和 mod_openh264(基于 Cisco OpenH264)两个模块实现。
VP8
VP8 是 WebRTC 的必选视频编解码器之一,由 Google 开发并开源。FreeSWITCH 通过 mod_av 模块提供 VP8 的编解码支持。VP8 的主要特点包括:
免专利费,适合开源项目
良好的错误恢复能力
支持时间可伸缩性(Temporal Scalability)
H.264
H.264 是目前最广泛使用的视频编解码器,FreeSWITCH 提供两种方式支持:
mod_av: 基于 FFmpeg/libav 库,提供完整的 H.264 编解码能力, 支持多种 profile(Baseline, Main, High)和 level。
mod_openh264: 基于 Cisco 开源的 OpenH264 库,仅支持 Baseline Profile, 但免专利费(Cisco 已支付相关费用)。
<!-- 在 vars.xml 中启用视频编解码器 -->
<X-PRE-PROCESS cmd="set"
data="global_codec_prefs=OPUS,PCMU,PCMA,VP8,H264"/>
<X-PRE-PROCESS cmd="set"
data="outbound_codec_prefs=OPUS,PCMU,PCMA,VP8,H264"/>
H.265 (HEVC) 支持状态
截至目前,FreeSWITCH 对 H.265/HEVC 的支持仍处于实验阶段。由于 H.265 的专利许可 问题较为复杂,且 WebRTC 标准尚未将其列为必选编解码器,因此在生产环境中使用 H.265 需要谨慎评估。未来随着 AV1 编解码器的成熟,FreeSWITCH 可能会优先支持 AV1 而非 H.265。
编解码器 |
提供模块 |
专利状态 |
WebRTC 支持 |
备注 |
|---|---|---|---|---|
VP8 |
mod_av |
免费 |
必选 |
Google 开源,兼容性好 |
H.264 |
mod_av / mod_openh264 |
需授权(OpenH264 免费) |
广泛支持 |
最通用的视频编解码器 |
H.265 |
实验性 |
需授权 |
尚未标准化 |
不建议生产使用 |
VP9 |
mod_av(部分) |
免费 |
可选 |
压缩效率优于 VP8 |
编解码器协商与转码
编解码器协商是 VoIP 通信中的关键环节,它决定了通话双方使用哪种编解码器进行 媒体传输。FreeSWITCH 提供了灵活的协商机制和强大的转码能力。
SDP 中的编解码器协商
在 SIP 会话建立过程中,编解码器协商通过 SDP(Session Description Protocol) 的 Offer/Answer 模型完成:
主叫方在 INVITE 请求中携带 SDP Offer,列出其支持的编解码器列表
FreeSWITCH 根据配置的偏好顺序,从 Offer 中选择匹配的编解码器
被叫方收到 FreeSWITCH 转发的 Offer 后,返回 SDP Answer
最终确定双方使用的编解码器
编解码器偏好顺序
FreeSWITCH 支持多个层级的编解码器偏好设置:
<!-- 全局偏好(vars.xml) -->
<X-PRE-PROCESS cmd="set"
data="global_codec_prefs=OPUS,G722,PCMU,PCMA,VP8,H264"/>
<!-- SIP Profile 级别偏好(sip_profiles/internal.xml) -->
<param name="inbound-codec-prefs" value="OPUS,G722,PCMU,PCMA"/>
<param name="outbound-codec-prefs" value="OPUS,G722,PCMU,PCMA"/>
<!-- 拨号计划中针对单个呼叫设置 -->
<action application="set"
data="absolute_codec_string=OPUS,PCMU"/>
<action application="export"
data="absolute_codec_string=OPUS,PCMU"/>
延迟协商(Late Negotiation)
默认情况下,FreeSWITCH 在收到 INVITE 时立即进行编解码器协商(Early Negotiation)。 启用延迟协商后,FreeSWITCH 会等到呼叫被应答或桥接时才确定编解码器, 这样可以让两个通话端直接协商,减少不必要的转码。
<!-- 在 SIP Profile 中启用延迟协商 -->
<param name="inbound-late-negotiation" value="true"/>
转码的 CPU 开销
转码是指将一种编解码器的媒体流转换为另一种编解码器的过程。这是一个计算密集型操作, 尤其是视频转码。以下是一些经验数据:
转码类型 |
单核并发路数 |
说明 |
|---|---|---|
G.711 ↔ G.711 |
数千路 |
几乎无 CPU 开销 |
G.711 ↔ Opus |
200-500 路 |
中等 CPU 开销 |
G.711 ↔ G.729 |
100-300 路 |
较高 CPU 开销 |
VP8 ↔ H.264 |
5-20 路 |
极高 CPU 开销,应尽量避免 |
注解
在生产环境中,应尽量通过合理的编解码器协商策略来避免不必要的转码, 特别是视频转码。使用延迟协商和编解码器透传是减少转码的有效手段。
媒体代理与媒体绕行
FreeSWITCH 提供了三种媒体处理模式,适用于不同的应用场景:
默认模式(Media Proxy)
在默认模式下,所有 RTP 媒体流都经过 FreeSWITCH。FreeSWITCH 完全参与媒体处理, 可以进行转码、录音、播放提示音等操作。
终端 A <--RTP--> FreeSWITCH <--RTP--> 终端 B
(完全媒体处理)
代理媒体模式(Proxy Media)
在代理媒体模式下,RTP 流仍然经过 FreeSWITCH,但 FreeSWITCH 不对媒体内容进行 解码或处理,仅做透明转发。这种模式保留了 NAT 穿越能力,同时降低了 CPU 开销。
<!-- 在拨号计划中启用代理媒体 -->
<action application="set" data="proxy_media=true"/>
<action application="bridge" data="sofia/gateway/provider/$1"/>
终端 A <--RTP--> FreeSWITCH <--RTP--> 终端 B
(透明转发,不解码)
媒体绕行模式(Bypass Media)
在绕行模式下,RTP 流直接在两个终端之间传输,完全不经过 FreeSWITCH。 FreeSWITCH 仅处理 SIP 信令。这种模式最大程度地降低了服务器负载和媒体延迟, 但失去了录音、转码等媒体处理能力。
<!-- 在拨号计划中启用媒体绕行 -->
<action application="set" data="bypass_media=true"/>
<action application="bridge" data="sofia/gateway/provider/$1"/>
终端 A <------------ RTP ------------> 终端 B
FreeSWITCH (仅信令)
特性 |
默认模式 |
代理媒体 |
媒体绕行 |
说明 |
|---|---|---|---|---|
RTP 经过 FS |
是 |
是 |
否 |
绕行模式 RTP 直连 |
转码能力 |
支持 |
不支持 |
不支持 |
仅默认模式可转码 |
录音能力 |
支持 |
不支持 |
不支持 |
需要媒体经过 FS |
NAT 穿越 |
支持 |
支持 |
需端到端可达 |
代理模式保留 NAT 穿越 |
CPU 开销 |
高 |
低 |
极低 |
绕行模式几乎无开销 |
媒体延迟 |
较高 |
中等 |
最低 |
减少一跳降低延迟 |
录音与回放
FreeSWITCH 提供了强大的录音和回放功能,广泛应用于通话录音、IVR 系统、 语音信箱等场景。
录音功能(mod_record)
FreeSWITCH 支持多种录音方式和格式:
<!-- 在拨号计划中启动录音 -->
<action application="record_session" data="/recordings/${uuid}.wav"/>
<!-- 录制立体声(双声道,每个通话方一个声道) -->
<action application="set" data="RECORD_STEREO=true"/>
<action application="record_session"
data="/recordings/${uuid}-stereo.wav"/>
<!-- 使用 record 应用录制单段音频 -->
<action application="record" data="/recordings/msg.wav 60 200 5"/>
<!-- 参数: 文件路径 最大秒数 静音阈值 静音超时秒数 -->
支持的录音格式
格式 |
扩展名 |
所需模块 |
说明 |
|---|---|---|---|
WAV (PCM) |
.wav |
内置 |
无损格式,文件较大 |
MP3 |
.mp3 |
mod_shout |
有损压缩,文件较小 |
OGG Vorbis |
.ogg |
mod_ogg |
开源有损压缩格式 |
回放功能
<!-- 播放音频文件 -->
<action application="playback" data="/sounds/welcome.wav"/>
<!-- 播放并等待 DTMF 输入 -->
<action application="play_and_get_digits"
data="1 4 3 5000 # /sounds/enter_pin.wav
/sounds/invalid.wav pin_result \d+"/>
<!-- 使用 say 应用进行 TTS 式播报 -->
<action application="say" data="zh NUMBER PRONOUNCED 12345"/>
通话录音的最佳实践
在生产环境中进行通话录音时,建议注意以下几点:
使用立体声录音以便区分通话双方
选择合适的录音格式平衡质量和存储空间
合理规划录音文件的存储路径和命名规则
定期清理过期的录音文件,避免磁盘空间耗尽
注意录音的法律合规要求
DTMF 处理
DTMF(Dual-Tone Multi-Frequency,双音多频)信号在 VoIP 通信中有三种传输方式, FreeSWITCH 全部支持并可在它们之间进行转换。
RFC 2833 (telephone-event)
这是 VoIP 中最常用的 DTMF 传输方式,将 DTMF 信号编码为特殊的 RTP 事件包 (通常使用 payload type 101)。
RTP Header | Payload Type: 101 | Event: 1 | Duration: 800 |
带内 DTMF(In-band DTMF)
将 DTMF 音调直接编码在音频流中。这种方式兼容性最好,但在使用低比特率编解码器 (如 G.729)时可能导致 DTMF 检测失败。
SIP INFO
通过 SIP INFO 消息在信令通道中传输 DTMF 信息。这种方式不依赖 RTP 流, 但可能受到信令延迟的影响。
SIP INFO sip:user@host
Content-Type: application/dtmf-relay
Signal=1
Duration=250
DTMF 模式配置
<!-- 在 SIP Profile 中设置 DTMF 模式 -->
<param name="dtmf-type" value="rfc2833"/>
<!-- 可选值: rfc2833, info, none -->
<!-- 在拨号计划中动态切换 DTMF 模式 -->
<action application="set" data="dtmf_type=rfc2833"/>
<!-- 启用带内 DTMF 检测 -->
<action application="start_dtmf"/>
<!-- 生成 DTMF 音调 -->
<action application="send_dtmf" data="1234#"/>
DTMF 检测与应用
FreeSWITCH 提供了丰富的 DTMF 检测和处理机制:
<!-- 绑定 DTMF 按键到动作 -->
<action application="bind_digit_action"
data="my_digits,~^\d{4}#$,exec:execute_extension,
check_pin XML default"/>
<!-- 在 IVR 中收集 DTMF 输入 -->
<action application="play_and_get_digits"
data="4 4 3 10000 # /sounds/enter_pin.wav
/sounds/error.wav digits_result \d{4}"/>
音频处理
FreeSWITCH 提供了丰富的音频处理功能,满足各种通信场景的需求。
音调生成(mod_tone_stream)
mod_tone_stream 模块可以生成各种标准音调,如忙音、回铃音、拨号音等:
<!-- 播放北美标准回铃音 -->
<action application="playback"
data="tone_stream://%(2000,4000,440,480)"/>
<!-- 播放忙音 -->
<action application="playback"
data="tone_stream://%(500,500,480,620);loops=-1"/>
<!-- 播放自定义频率音调 -->
<action application="playback"
data="tone_stream://%(1000,0,800)"/>
等待音乐(Music on Hold)
FreeSWITCH 通过 mod_local_stream 模块提供高效的等待音乐功能:
<!-- local_stream.conf.xml 配置 -->
<configuration name="local_stream.conf" description="Stream Files">
<directory name="moh/8000" path="$${sounds_dir}/music/8000">
<param name="rate" value="8000"/>
<param name="shuffle" value="true"/>
<param name="channels" value="1"/>
<param name="interval" value="20"/>
<param name="timer-name" value="soft"/>
</directory>
</configuration>
<!-- 在拨号计划中使用等待音乐 -->
<action application="set" data="hold_music=local_stream://moh/8000"/>
静音检测(Silence Detection)
静音检测用于识别通话中的静默期,常用于语音信箱和录音场景:
<!-- 启用静音检测,200 为静音阈值,500ms 为超时 -->
<action application="set" data="silence_hits=500"/>
<action application="detect_silence" data="200 500"/>
舒适噪声(Comfort Noise)
在静音期间生成舒适噪声(CN),避免通话中出现"死寂"的感觉:
<!-- 启用舒适噪声生成 -->
<param name="comfort-noise" value="true"/>
<!-- 在 SDP 中协商 CN -->
<!-- payload type 13 通常用于 CN -->
RTP 配置与优化
RTP(Real-time Transport Protocol)是 FreeSWITCH 媒体传输的基础协议。 合理的 RTP 配置对通话质量至关重要。
RTP 端口范围
<!-- switch.conf.xml 中配置 RTP 端口范围 -->
<param name="rtp-start-port" value="16384"/>
<param name="rtp-end-port" value="32768"/>
<!-- 确保防火墙开放对应的 UDP 端口范围 -->
端口范围的大小决定了 FreeSWITCH 能同时处理的最大媒体流数量。 每个媒体流需要两个端口(一个用于 RTP,一个用于 RTCP),因此可用端口数除以 2 即为最大并发媒体流数。
RTP 定时器
FreeSWITCH 支持多种 RTP 定时器实现:
<!-- 使用软定时器(默认) -->
<param name="rtp-timer-name" value="soft"/>
<!-- 定时器间隔(毫秒) -->
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
抖动缓冲区(Jitter Buffer)
抖动缓冲区用于平滑网络抖动对音频质量的影响:
<!-- 启用抖动缓冲区 -->
<action application="set"
data="jitterbuffer_msec=60:200:20"/>
<!-- 参数: 初始大小:最大大小:最大漂移 (毫秒) -->
<!-- 视频抖动缓冲区 -->
<action application="set"
data="rtp_video_jitterbuffer_msec=200:1000:50"/>
RTCP 配置
RTCP(RTP Control Protocol)提供媒体流的质量反馈信息:
<!-- 启用 RTCP -->
<param name="rtcp-audio-interval-msec" value="5000"/>
<param name="rtcp-video-interval-msec" value="2000"/>
对称 RTP(Symmetric RTP)
对称 RTP 有助于 NAT 穿越,使 FreeSWITCH 将 RTP 包发送到接收 RTP 包的同一地址:
<!-- 在 SIP Profile 中启用对称 RTP -->
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="ext-rtp-ip" value="auto-nat"/>
WebRTC 相关的 RTP 配置
在处理 WebRTC 呼叫时,需要额外配置 DTLS-SRTP 和 ICE:
<!-- 在 SIP Profile 中启用 WebRTC 支持 -->
<param name="tls" value="true"/>
<param name="wss-binding" value=":7443"/>
<!-- 在拨号计划中为 WebRTC 呼叫设置媒体参数 -->
<action application="set" data="rtp_secure_media=true"/>
<action application="set"
data="rtp_secure_media_suites=
AEAD_AES_256_GCM_8|
AEAD_AES_128_GCM_8|
AES_CM_256_HMAC_SHA1_80|
AES_CM_128_HMAC_SHA1_80"/>
RTP 优化建议
端口范围: 根据预期并发量合理设置端口范围,避免端口耗尽
抖动缓冲区: 根据网络质量调整抖动缓冲区大小,过大会增加延迟,过小会导致丢包
RTCP: 启用 RTCP 以便监控通话质量,及时发现和定位问题
对称 RTP: 在 NAT 环境中务必启用对称 RTP
QoS 标记: 配置 DSCP 标记以确保 RTP 包在网络中获得优先处理
<!-- 设置 RTP 包的 DSCP/TOS 值 -->
<param name="rtp-tos-value" value="184"/>
<!-- 184 = 0xB8 = EF (Expedited Forwarding) -->
参考资料
FreeSWITCH 官方文档: https://freeswitch.org/confluence/
FreeSWITCH 权威指南(The Definitive Guide to FreeSWITCH)
RFC 3550 - RTP: A Transport Protocol for Real-Time Applications
RFC 2833 - RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals
RFC 6716 - Definition of the Opus Audio Codec
RFC 7742 - WebRTC Video Processing and Codec Requirements
RFC 7874 - WebRTC Audio Codec and Processing Requirements
FreeSWITCH mod_opus 文档: https://freeswitch.org/confluence/display/FREESWITCH/mod_opus
FreeSWITCH Codec Negotiation: https://freeswitch.org/confluence/display/FREESWITCH/Codec+Negotiation
WebRTC 与 FreeSWITCH 集成最佳实践