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

相关推荐
渡我白衣1 小时前
计算机组成原理(3):计算机软件
java·c语言·开发语言·jvm·c++·人工智能·python
小龙报1 小时前
【C语言初阶】动态内存分配实战指南:C 语言 4 大函数使用 + 经典笔试题 + 柔性数组优势与内存区域
android·c语言·开发语言·数据结构·c++·算法·visual studio
小龙报1 小时前
【算法通关指南:算法基础篇(三)】一维差分专题:1.【模板】差分 2.海底高铁
android·c语言·数据结构·c++·算法·leetcode·visual studio
小李小李快乐不已2 小时前
图论理论基础(5)
数据结构·c++·算法·机器学习·动态规划·图论
承渊政道2 小时前
C++学习之旅【C++基础知识介绍】
c语言·c++·学习·程序人生
枫叶丹42 小时前
【Qt开发】Qt窗口(七) -> QColorDialog 颜色对话框
c语言·开发语言·c++·qt
闻缺陷则喜何志丹2 小时前
【计算几何】三角函数的和角公式、矢量旋转
c++·数学·计算几何·三角函数和角公式·矢量旋转
渡我白衣2 小时前
计算机组成原理(2):计算机硬件的基本组成
运维·服务器·网络·c++·人工智能·网络协议·dubbo
AI视觉网奇10 小时前
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr
开发语言·c++·算法