前言

WebRTC 是 Google 开源的实时音视频通信框架,内置了音视频采集、编解码、传输、渲染的完整链路,是构建实时通信应用的利器。然而,WebRTC 的标准使用方式——PeerConnection + SDP 协商——是为 P2P 通信设计的,直接用于构建 SFU 视频会议系统时,会遇到不少痛点:

  • SDP 协商过于笨重:一次 SDP offer/answer 动辄几千字节的文本协商,难以精细控制
  • P2P 模型不适合 SFU:视频会议需要服务端做流转发,P2P 模型无法满足
  • ICE/DTLS 握手延迟高:完整的 ICE 候选收集 + DTLS 握手过程耗时较长
  • 难以实现按需推拉流:标准 WebRTC 中流的方向在协商时确定,难以动态控制

本文将介绍我们如何基于 WebRTC 的底层能力,摒弃 PeerConnection,打造一套轻量级 SFU 视频会议系统。


核心设计思路

1. 去掉 PeerConnection,保留 MediaEngine

WebRTC 的分层架构大致如下:

┌─────────────────────────────────┐
│      PeerConnection (应用层)     │  ← 我们去掉了这一层
├─────────────────────────────────┤
│      Channel / Transport        │  ← 我们重写了这一层
├─────────────────────────────────┤
│      MediaEngine (编解码/处理)   │  ← 完整保留
├─────────────────────────────────┤
│      RTP/RTCP (协议层)          │  ← 完整保留
└─────────────────────────────────┘

PeerConnection 做了太多事情:SDP 协商、ICE 穿越和 DTLS 握手等等,对于 SFU 架构来说大部分是不必要的。但 MediaEngine 是 WebRTC 的精华所在——它包含了:

  • OPUS/VP8/VP9/H264 编解码器
  • 音频处理(AEC 回声消除、NS 噪声抑制、AGC 自动增益)
  • 视频处理(抖动缓冲、丢包 concealment)
  • RTP/RTCP 协议栈
  • 带宽估计(GCC)与拥塞控制

我们的策略是:保留 MediaEngine,重写传输和控制层

2. 用 KCP 替代 ICE/DTLS/SRTP

标准 WebRTC 的传输链路是:

ICE (NAT穿越) → DTLS (加密握手) → SRTP (加密RTP)

这条链路虽然安全可靠,但存在几个问题:

  • 握手延迟:ICE + DTLS 至少需要多个 RTT
  • 实现复杂:ICE 的 full/trickle 候选收集逻辑复杂
  • SRTP 对 SFU 不友好:每对 Peer 都需要独立的 DTLS 会话和 SRTP 上下文

我们选择用 KCP over UDP 替代:

KCP (可靠传输) → UDP (RTP透传)
  • 信令数据走 KCP 可靠通道,保证 JSON 消息的可靠投递
  • RTP/RTCP 数据走 UDP 透传,保证媒体传输的低延迟
  • NAT 穿越通过 KCP 的连接握手中内置的重定向机制解决

3. 推拉流模型替代 SDP 协商

标准 WebRTC 中,音视频流的添加和方向控制通过 SDP 协商完成。在我们的系统中,采用 Publish/Subscribe 模型

┌─────────┐    Publish     ┌─────────┐    Forward     ┌─────────┐
│  推流端  │──────────────▶│   SFU   │──────────────▶│  拉流端  │
│ Client A │   (推一路流)   │ Server  │   (按需转发)   │ Client B │
└─────────┘                └─────────┘                └─────────┘
  • 客户端通过 Publish 接口发布本地音视频流
  • 客户端通过 Subscribe 接口订阅远端音视频流
  • 服务端 SFU 按需转发,支持灵活的多路流控制

这种方式的优势:

  • 按需推拉:只有有人订阅时才转发,节省带宽
  • 动态控制:随时可以开关音视频,无需重新协商
  • 简单直观:API 语义清晰,不需要理解 SDP

系统架构

┌──────────────────────────────────────────────────────┐
│                     客户端 (Client)                    │
│                                                       │
│  ┌───────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │MediaClient│─▶│MediaConnection│─▶│ MediaChannel  │  │
│  │ (业务层)  │  │ (连接管理)   │  │(音视频通道)   │  │
│  └─────┬─────┘  └──────┬───────┘  └───────┬───────┘  │
│        │               │                   │          │
│  ┌─────▼──────┐ ┌──────▼──────┐  ┌────────▼───────┐  │
│  │Client      │ │RtpTransport │  │VoiceChannel /  │  │
│  │Transport   │▶│(RTP分发)    │▶│VideoChannel    │  │
│  │(信令+RTP)  │ └──────┬──────┘  └────────────────┘  │
│  └─────┬──────┘        │                              │
│        │         ┌─────▼───────┐                       │
│        │         │ MediaNetwork│                       │
│        │         │ (KCP传输)   │                       │
│        │         └─────┬───────┘                       │
│        │               │  UDP                          │
└────────┼───────────────┼───────────────────────────────┘
         │               │
         ▼               ▼
┌──────────────────────────────────────────────────────┐
│                  SFU 媒体服务器                        │
│           (KCP 信令 + RTP 流转发)                      │
└──────────────────────────────────────────────────────┘

各层职责

层次 模块 职责
业务层 MediaClient 推拉流生命周期管理、流信息维护
连接层 MediaConnection 音视频通道管理、轨道添加/移除
通道层 VoiceChannel / VideoChannel 编解码、RTP 收发
传输层 RtpTransport RTP/RTCP 包分发(按 SSRC)
复用层 ClientTransport 信令通道与 RTP 通道复用
网络层 MediaNetwork KCP Socket 管理、JSON-RPC
协议层 KCP 可靠传输、握手、心跳、重定向

关键技术决策总结

决策 选择 理由
架构模式 SFU 服务端转发,适合多方会议
传输协议 KCP over UDP 可靠信令 + 低延迟媒体
信令协议 JSON-RPC 2.0 简洁、易调试、易扩展
流控制 Publish/Subscribe 灵活、按需、动态
编解码 WebRTC 内置 OPUS + VP8/H264,硬件加速
拥塞控制 可注入 GCC/自定义 通过工厂接口灵活替换

系列文章预告

本系列共五篇,后续文章将分别深入以下主题:

  1. 架构总览与设计思路(本文)
  2. KCP 传输层设计与实现 — 详解如何基于 KCP 构建双通道传输
  3. 绕过 PeerConnection 的媒体引擎集成 — 如何直接使用 WebRTC 的 MediaEngine
  4. 信令协议与推拉流模型 — JSON-RPC 协议设计与 Publish/Subscribe 实现
  5. 从连接建立到音视频交付的完整流程 — 端到端流程串联

小结

本文介绍了我们基于 WebRTC 构建视频会议系统的整体架构和核心设计思路。通过 去掉 PeerConnection、保留 MediaEngine、用 KCP 替代标准传输栈、用推拉流模型替代 SDP 协商,我们实现了一套架构简洁、延迟可控、灵活可扩展的视频会议系统。

下一篇我们将深入 KCP 传输层的设计与实现,看看如何在同一个 UDP 连接上同时传输可靠信令和实时媒体数据。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐