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 通信的各种需求。 以下是主要支持的音频编解码器及其特性:

FreeSWITCH 支持的音频编解码器

编解码器

采样率 (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 提供两种方式支持:

  1. mod_av: 基于 FFmpeg/libav 库,提供完整的 H.264 编解码能力, 支持多种 profile(Baseline, Main, High)和 level。

  2. 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。

FreeSWITCH 视频编解码器对比

编解码器

提供模块

专利状态

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 模型完成:

  1. 主叫方在 INVITE 请求中携带 SDP Offer,列出其支持的编解码器列表

  2. FreeSWITCH 根据配置的偏好顺序,从 Offer 中选择匹配的编解码器

  3. 被叫方收到 FreeSWITCH 转发的 Offer 后,返回 SDP Answer

  4. 最终确定双方使用的编解码器

编解码器偏好顺序

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 开销

转码是指将一种编解码器的媒体流转换为另一种编解码器的过程。这是一个计算密集型操作, 尤其是视频转码。以下是一些经验数据:

转码 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"/>

通话录音的最佳实践

在生产环境中进行通话录音时,建议注意以下几点:

  1. 使用立体声录音以便区分通话双方

  2. 选择合适的录音格式平衡质量和存储空间

  3. 合理规划录音文件的存储路径和命名规则

  4. 定期清理过期的录音文件,避免磁盘空间耗尽

  5. 注意录音的法律合规要求

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 优化建议

  1. 端口范围: 根据预期并发量合理设置端口范围,避免端口耗尽

  2. 抖动缓冲区: 根据网络质量调整抖动缓冲区大小,过大会增加延迟,过小会导致丢包

  3. RTCP: 启用 RTCP 以便监控通话质量,及时发现和定位问题

  4. 对称 RTP: 在 NAT 环境中务必启用对称 RTP

  5. QoS 标记: 配置 DSCP 标记以确保 RTP 包在网络中获得优先处理

<!-- 设置 RTP 包的 DSCP/TOS 值 -->
<param name="rtp-tos-value" value="184"/>
<!-- 184 = 0xB8 = EF (Expedited Forwarding) -->

参考资料

  1. FreeSWITCH 官方文档: https://freeswitch.org/confluence/

  2. FreeSWITCH 权威指南(The Definitive Guide to FreeSWITCH)

  3. RFC 3550 - RTP: A Transport Protocol for Real-Time Applications

  4. RFC 2833 - RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals

  5. RFC 6716 - Definition of the Opus Audio Codec

  6. RFC 7742 - WebRTC Video Processing and Codec Requirements

  7. RFC 7874 - WebRTC Audio Codec and Processing Requirements

  8. FreeSWITCH mod_opus 文档: https://freeswitch.org/confluence/display/FREESWITCH/mod_opus

  9. FreeSWITCH Codec Negotiation: https://freeswitch.org/confluence/display/FREESWITCH/Codec+Negotiation

  10. WebRTC 与 FreeSWITCH 集成最佳实践