mediasoup源码走读(三)Node.js 控制面

3.1. 总体架构图与类图

3.1.1 系统架构图

Node.js 控制面 Channel C++ Worker 数据面 libuv 事件循环 ICE/DTLS 协商 RTP/RTCP 处理 媒体路由管理 Producer/Consumer API WebRTC 客户端 FFmpeg/GStreamer 集成 HTTP HLS 接口

  • 双层架构:Node.js 层负责业务逻辑控制,C++ Worker 层处理媒体底层逻辑
  • 通信桥梁ChannelPayloadChannel 实现跨进程通信
  • 扩展能力:支持 WebRTC、RTP/RTCP 原生协议、FFmpeg 等多种接入方式

3.1.2 核心类图

1 1 1 N 1 N 1 1..N 1 1..N 1 1 1 1 Channel +emit(event, data) : void +on(event, handler) : void Router +createProducer() : Producer +createConsumer() : Consumer Producer +sendRtp(packet) : void +pause() : void +resume() : void Consumer +onRtp(packet) : void +requestKeyFrame() : void WebRtcTransport +connect(options) : void +produce(stream) : Producer +consume(producerId) : Consumer PayloadChannel +send(data) : void Worker

  • 核心关系Router 是媒体流容器,通过 WebRtcTransport 连接客户端
  • 数据传输Producer/Consumer 通过 PayloadChannel 发送大包数据
  • 生命周期Channel 统一管理控制面事件,Worker 管理数据面实例

3.2. 信令交互模块

3.2.1 Channel 信令通信时序

JS Channel Worker emit('router.create', options) IPC发送消息 回复 routerId 触发 'router.created' 事件 JS Channel Worker

  1. JS 层调用 emit() 发送创建房间请求
  2. Channel 通过 IPC 通道将消息传递给 Worker
  3. Worker 处理完底层逻辑后返回结果
  4. Channel 在 JS 层触发事件通知业务逻辑

源码说明(lib/Channel.js):

javascript 复制代码
/**
 * 信令通道核心类
 * 负责 JS 层与 Worker 的双向通信
 */
class Channel {
  /**
   * 发送信令消息到 Worker
   * @param {string} event - 事件名称
   * @param {Object} data - 消息体
   */
  emit(event, data) {
    // 1. 构建消息对象
    const message = {
      event,
      data
    };
    
    // 2. 通过 IPC 通道发送消息
    this._worker.send(message);
  }

  /**
   * 监听 Worker 返回的事件
   * @param {string} event - 事件名称
   * @param {Function} handler - 事件处理函数
   */
  on(event, handler) {
    if (!this._events[event]) {
      this._events[event] = [];
    }
    
    // 3. 注册事件监听器
    this._events[event].push(handler);
  }
}

3.3. 路由器管理模块

3.3.1 Router 创建时序

JS Channel Worker emit('router.create', options) 创建 Router 请求 返回 routerId 触发 'router.created' 事件 JS Channel Worker

  1. JS 层调用 createRouter() 发起创建请求
  2. Channel 转发请求到 Worker
  3. Worker 创建底层 C++ Router 实例
  4. 通过事件通知 JS 层创建完成

源码说明(lib/Router.js):

javascript 复制代码
/**
 * 房间管理类
 * 对应底层 C++ 的 Router 实例
 */
class Router {
  /**
   * 创建房间实例
   * @param {Channel} channel - 通信通道
   * @param {Object} options - 创建参数
   */
  constructor(channel, options) {
    this._id = options.id || generateId();
    
    // 1. 通过 Channel 发送创建请求
    channel.emit('router.create', {
      id: this._id,
      options
    });
    
    // 2. 监听创建完成事件
    channel.on('router.created', (routerId) => {
      if (routerId === this._id) {
        this._emit('created');
      }
    });
  }
}

3.4. 生产者管理模块

3.4.1 Producer 创建时序

JS Channel Worker emit('producer.create', options) 创建 Producer 请求 返回 producerId 触发 'producer.created' 事件 JS Channel Worker

  1. JS 层调用 produce() 创建生产者
  2. Channel 将请求转发给 Worker
  3. Worker 创建底层 C++ Producer
  4. 通过事件通知 JS 层创建完成

源码说明(lib/Producer.js):

javascript 复制代码
/**
 * 媒体生产者类
 * 负责将媒体流推送到房间
 */
class Producer {
  /**
   * 创建生产者实例
   * @param {Channel} channel - 通信通道
   * @param {string} routerId - 所属房间ID
   * @param {Object} options - 创建参数
   */
  constructor(channel, routerId, options) {
    this._id = options.id || generateId();
    
    // 1. 发送创建请求
    channel.emit('producer.create', {
      routerId,
      producerId: this._id,
      options
    });
    
    // 2. 监听关闭事件
    channel.on('producer.closed', (producerId) => {
      if (producerId === this._id) {
        this._emit('close');
      }
    });
  }
}

3.5. 消费者管理模块

3.5.1 Consumer 创建时序

JS Channel Worker emit('consumer.create', options) 创建 Consumer 请求 返回 consumerId 触发 'consumer.created' 事件 JS Channel Worker

  1. JS 层调用 createConsumer() 创建消费者
  2. Channel 转发请求到 Worker
  3. Worker 创建底层 C++ Consumer
  4. 通过事件通知 JS 层创建完成

源码说明(lib/Consumer.js):

javascript 复制代码
/**
 * 媒体消费者类
 * 负责接收并消费媒体流
 */
class Consumer {
  /**
   * 创建消费者实例
   * @param {Channel} channel - 通信通道
   * @param {string} routerId - 所属房间ID
   * @param {string} producerId - 对应生产者ID
   */
  constructor(channel, routerId, producerId) {
    this._id = generateId();
    
    // 1. 发送创建请求
    channel.emit('consumer.create', {
      routerId,
      producerId,
      consumerId: this._id
    });
    
    // 2. 监听 RTP 包事件
    channel.on('consumer.rtp', (consumerId, packet) => {
      if (consumerId === this._id) {
        this._emit('rtp', packet);
      }
    });
  }
}

3.6. 数据通道模块

3.6.1 WebRtcTransport 连接时序

JS Channel Worker emit('transport.connect', options) 连接请求 返回连接状态 触发 'transport.connected' 事件 JS Channel Worker

  1. JS 层调用 connect() 建立传输通道
  2. Channel 将 DTLS 参数传递给 Worker
  3. Worker 完成 ICE/DTLS 协商
  4. 通过事件通知 JS 层连接建立成功

源码说明(lib/WebRtcTransport.js):

javascript 复制代码
/**
 * WebRTC 传输通道类
 * 负责媒体传输的底层连接
 */
class WebRtcTransport {
  /**
   * 建立连接
   * @param {Object} options - 连接参数(包含 DTLS 参数)
   */
  connect(options) {
    // 1. 通过 Channel 发送连接请求
    this._channel.emit('transport.connect', {
      transportId: this._id,
      options
    });
    
    // 2. 监听连接完成事件
    this._channel.on('transport.connected', (transportId) => {
      if (transportId === this._id) {
        this._emit('connected');
      }
    });
  }
}

3.7. 控制面与数据面交互

3.7.1 RTP 包传输时序

Producer WebRtcTransport Channel Worker sendRtp(packet) emit('transport.sendRtp', packet) 传输 RTP 包 (ACK) 'transport.rtpSent' Producer WebRtcTransport Channel Worker

  1. Producer 调用 sendRtp() 发送 RTP 包
  2. 通过 WebRtcTransport 传递到 Channel
  3. Channel 使用 PayloadChannel 传输大包
  4. Worker 处理后返回确认信息

源码说明(lib/PayloadChannel.js):

javascript 复制代码
/**
 * 大包传输通道
 * 优化 RTP 包的传输效率
 */
class PayloadChannel {
  /**
   * 发送大包数据
   * @param {ArrayBuffer} data - 待发送数据
   */
  send(data) {
    // 1. 使用 UDP 套接字发送
    this._socket.send(
      data,
      0,
      data.byteLength,
      this._port,
      this._host
    );
  }
}

3.8. 完整业务流程

3.8.1 端到端媒体传输流程

Camera Producer WebRtcTransport Consumer Decoder captureFrame() sendRtp(packet) receiveRtp(packet) decode(packet) render(frame) Camera Producer WebRtcTransport Consumer Decoder

  1. 摄像头采集帧数据
  2. Producer 打包为 RTP 包
  3. 通过 WebRtcTransport 传输
  4. Consumer 接收并解码
  5. 最终渲染显示

3.9. 关键设计

模块 核心价值 代码体现
信令交互 解耦业务逻辑 Channel.js 的事件驱动模型
路由管理 隔离媒体拓扑 Router.js 的房间隔离机制
生产者管理 流量控制 Producer.js 的 pause/resume 实现
消费者管理 QoS 保障 Consumer.js 的 NackGenerator 集成
数据通道 低延迟传输 PayloadChannel.js 的 UDP 优化

相关推荐
小镇敲码人6 小时前
深入剖析华为CANN框架下的Ops-CV仓库:从入门到实战指南
c++·python·华为·cann
晚霞的不甘6 小时前
CANN 编译器深度解析:TBE 自定义算子开发实战
人工智能·架构·开源·音视频
愚公搬代码6 小时前
【愚公系列】《AI短视频创作一本通》016-AI短视频的生成(AI短视频运镜方法)
人工智能·音视频
张张努力变强7 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
小镇敲码人7 小时前
探索CANN框架中TBE仓库:张量加速引擎的优化之道
c++·华为·acl·cann·ops-nn
那个村的李富贵7 小时前
CANN赋能AIGC“数字人”革命:实时视频换脸与表情驱动实战
aigc·音视频
平安的平安7 小时前
面向大模型算子开发的高效编程范式PyPTO深度解析
c++·mfc
June`7 小时前
muduo项目排查错误+测试
linux·c++·github·muduo网络库
晚霞的不甘7 小时前
CANN 支持强化学习:从 Isaac Gym 仿真到机械臂真机控制
人工智能·神经网络·架构·开源·音视频
C++ 老炮儿的技术栈7 小时前
VS2015 + Qt 实现图形化Hello World(详细步骤)
c语言·开发语言·c++·windows·qt