FreeSWITCH Media Bug 框架详解

本文系统性整理 FreeSWITCH Media Bug 的设计理念、核心数据结构、API 使用方式以及典型应用场景,适合 FreeSWITCH / VoIP / 媒体处理 方向的开发者作为参考文档或源码导读。


目录


一、概述

1. 什么是 Media Bug?

Media Bug 是 FreeSWITCH 内部提供的一套 媒体流拦截(Hook)与处理框架 。开发者可以在通话会话(switch_core_session_t)中动态挂载一个或多个 Media Bug,用于捕获、分析、修改音频 / 视频 / 文本流。

它的核心思想是:

在编解码之后、媒体送达应用之前,提供一个可插拔的处理点。

支持的能力包括:

  • 🎙 音频录制(读 / 写流)

  • 🔁 实时音频替换与注入

  • 📊 语音分析(VAD / DTMF / Tone / ASR)

  • 🎥 视频捕获、处理、监控

  • 👂 通话监听(Spy / Whisper)

  • 💬 文本流(Text / RTCP / Data channel)处理


2. 典型应用场景

  • 通话录音(单声道 / 立体声)

  • 实时语音识别(ASR)

  • 语音信箱 / 应答机检测(VMD / AVMD)

  • 回声消除、降噪、语音增强

  • 视频录制、截图、水印、转码

  • 通话质量监控(MOS / RTP)

  • 通话注入提示音、混音


二、核心数据结构

1. switch_media_bug_t

Media Bug 的核心结构体,定义于:

cpp 复制代码
src/include/private/switch_core_pvt.h
cpp 复制代码
struct switch_media_bug {
    /* 音频缓冲区 */
    switch_buffer_t *raw_write_buffer;      // 写入流缓冲
    switch_buffer_t *raw_read_buffer;       // 读取流缓冲

    /* 帧替换(REPLACE 模式) */
    switch_frame_t *read_replace_frame_in;
    switch_frame_t *read_replace_frame_out;
    switch_frame_t *write_replace_frame_in;
    switch_frame_t *write_replace_frame_out;

    /* 原生帧 */
    switch_frame_t *native_read_frame;
    switch_frame_t *native_write_frame;

    /* 回调与上下文 */
    switch_media_bug_callback_t callback;
    void *user_data;

    /* 线程安全 */
    switch_mutex_t *read_mutex;
    switch_mutex_t *write_mutex;

    /* 会话信息 */
    switch_core_session_t *session;
    uint32_t flags;
    uint8_t ready;
    time_t stop_time;
    switch_thread_id_t thread_id;

    /* 标识 */
    char *function;
    char *target;

    /* 编解码信息 */
    switch_codec_implementation_t read_impl;
    switch_codec_implementation_t write_impl;

    /* 录制相关 */
    uint32_t record_frame_size;
    uint32_t record_pre_buffer_count;
    uint32_t record_pre_buffer_max;

    /* 视频相关 */
    switch_frame_t *video_ping_frame;
    switch_queue_t *read_video_queue;
    switch_queue_t *write_video_queue;
    switch_queue_t *spy_video_queue[2];
    switch_image_t *spy_img[2];
    switch_vid_spy_fmt_t spy_fmt;
    switch_thread_t *video_bug_thread;

    /* 文本流 */
    switch_buffer_t *text_buffer;
    char *text_framedata;
    uint32_t text_framesize;

    /* 链表 */
    switch_mm_t mm;
    struct switch_media_bug *next;

    /* 临时缓冲 */
    uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
    int16_t tmp[SWITCH_RECOMMENDED_BUFFER_SIZE];
};

💡 一个会话可以同时挂载 多个 Media Bug,它们以链表形式存在。


2. 回调函数类型

cpp 复制代码
typedef switch_bool_t (*switch_media_bug_callback_t)(
    switch_media_bug_t *bug,
    void *user_data,
    switch_abc_type_t type
);
  • bug:当前 Media Bug 实例

  • user_data:创建时传入的用户上下文

  • type:当前触发的回调类型


三、标志位说明

1. switch_media_bug_flag_t

标志位定义在:

cpp 复制代码
src/include/switch_types.h
标志位 说明
SMBF_READ_STREAM 捕获 incoming audio
SMBF_WRITE_STREAM 捕获 outgoing audio
SMBF_READ_REPLACE 替换读取流
SMBF_WRITE_REPLACE 替换写入流
SMBF_STEREO 立体声录制
SMBF_ANSWER_REQ 应答后才开始
SMBF_BRIDGE_REQ 桥接后才开始
SMBF_ONE_ONLY 同 function 只允许一个
SMBF_TAP_NATIVE_READ 原生读取帧
SMBF_TAP_NATIVE_WRITE 原生写入帧
SMBF_READ_VIDEO_STREAM 读取视频流
SMBF_VIDEO_PATCH 视频补丁
SMBF_READ_TEXT_STREAM 文本流

2. 标志位组合示例

cpp 复制代码
// 双向立体声录音
flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_STEREO;

// 仅应答后录制 incoming audio
flags = SMBF_READ_STREAM | SMBF_ANSWER_REQ;

// 替换 outgoing audio
flags = SMBF_WRITE_REPLACE;

四、回调类型

switch_abc_type_t

类型 触发时机
SWITCH_ABC_TYPE_INIT Bug 创建成功
SWITCH_ABC_TYPE_CLOSE Bug 移除
SWITCH_ABC_TYPE_READ 读取流数据
SWITCH_ABC_TYPE_WRITE 写入流数据
SWITCH_ABC_TYPE_READ_REPLACE 读取替换
SWITCH_ABC_TYPE_WRITE_REPLACE 写入替换
SWITCH_ABC_TYPE_READ_VIDEO_PING 视频心跳
SWITCH_ABC_TYPE_READ_TEXT 文本数据

返回值说明:

  • SWITCH_TRUE:继续执行

  • SWITCH_FALSE:停止并移除该 Media Bug


五、核心 API

1. 添加 Media Bug

cpp 复制代码
switch_core_media_bug_add(
    session,
    "record",
    filename,
    callback,
    user_data,
    0,
    flags,
    &bug
);

2. 移除 Media Bug

cpp 复制代码
switch_core_media_bug_remove(session, &bug);
switch_core_media_bug_remove_all_function(session, "record");

3. 读取混合音频

cpp 复制代码
switch_core_media_bug_read(bug, &frame, SWITCH_TRUE);

六、工作流程

1. 音频处理流程(简化)

复制代码
Codec Decode → Media Bug → 应用处理 → Codec Encode

2. 生命周期

  1. switch_core_media_bug_add

  2. INIT 回调

  3. READ / WRITE 回调

  4. switch_core_media_bug_remove

  5. CLOSE 回调


七、使用示例

示例:双向立体声录音

复制代码
flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_STEREO;

八、最佳实践

1. 线程安全

  • 回调运行在 媒体线程

  • 共享资源务必加锁

2. 内存管理

  • 使用 switch_core_session_alloc

  • 不要使用 malloc / free

3. 性能建议

  • 回调中避免阻塞

  • 使用异步队列

  • 仅订阅必要的流


附录

A. 关键源码

  • switch_core_media_bug.c

  • switch_core_pvt.h

B. 常见模块

  • mod_vmd

  • mod_avmd

  • mod_spy

  • mod_snapshot


总结

Media Bug 是 FreeSWITCH 媒体处理的基石能力之一。

通过合理使用 Media Bug,可以实现:

  • 高性能录音

  • 实时音频 / 视频处理

  • 通话监控与分析

  • ASR / TTS / AI 媒体接入

如果你在做 语音平台、呼叫中心、AI 语音、VoIP 内核开发,Media Bug 是绕不开的一块核心能力。


FreeSWITCH :1.10.x