WebRTC的服务器端架构:SFU与MCU深度对比

聊到WebRTC的服务器端架构,我不得不先说说自己的经历。几年前我接手一个视频会议项目,一开始想得挺简单——点对点通信嘛,浏览器原生支持。结果一上线,8个人开会,每个人的上行带宽就炸了。嗯,这就是典型的「没考虑服务器端架构」的坑。

说白了,WebRTC虽然主打P2P,但一旦超过3个人,你就得引入服务器。目前主流方案就两个:SFUMCU。今天咱们把它们掰开揉碎讲清楚。

为什么需要服务器?

先看一个最简单的场景:4个人视频会议。

  • 纯P2P方案:每个人要发3路视频,收3路视频。总共12路连接。
  • 引入服务器后:每个人只发1路给服务器,服务器负责分发。

你想想看,如果10个人开会,P2P方案每个人要处理9路视频。这带宽和CPU开销,普通笔记本根本扛不住。我见过一个项目,6个人开会,某位同事的MacBook风扇直接起飞——这就是没做服务器端架构的后果。

SFU vs MCU:核心区别

先给个直观对比:

特性 SFU(选择性转发单元) MCU(多点控制单元)
核心逻辑 只转发,不处理 混流,重新编码
服务器CPU负载 低(几乎为0) 高(需要转码)
客户端CPU负载 高(解码多路) 低(只解码1路)
带宽消耗 较高(多路独立流) 较低(1路合成流)
延迟 低(毫秒级转发) 高(需要等待合成)
灵活性 高(可选择性订阅) 低(所有人看到相同画面)

我个人习惯用一句话总结:SFU是快递员,MCU是厨师。快递员只管把包裹送到,不拆包;厨师要把所有食材混在一起炒成一盘菜。

SFU详解:选择性转发单元

SFU是目前最主流的方案。Zoom、Google Meet、腾讯会议,底层都是SFU架构。为什么?因为它简单、高效、灵活。

SFU的工作原理

SFU做的事情其实很纯粹:

  1. 接收每个参与者的音视频流
  2. 根据订阅关系,决定把哪些流转发给谁
  3. 不做任何解码、编码、混流操作

举个例子:会议室里有A、B、C三个人。A的摄像头对着白板,B在说话,C在听。

  • SFU会把A的视频流转发给B和C
  • 把B的音视频流转发给A和C
  • C的流可能只转发音频(如果C关了摄像头)

这里有个关键点:SFU可以按需转发。比如C的网络不好,SFU可以只转发音频,不转发视频。这在MCU里很难做到。

核心优势:SFU不修改媒体内容,所以延迟极低。我在项目中测过,端到端延迟通常在50ms以内,而MCU往往要200ms以上。

SFU的避坑指南

我曾经踩过一个坑:SFU虽然服务器负载低,但客户端负载高。有一次我们给一个教育平台做SFU,学生端用的是低配平板。结果8路视频同时解码,平板直接卡死。

解决方案:在SFU层做Simulcast( simulcast 编码),让服务器根据客户端能力选择合适的分辨率转发。比如平板只收360p,PC收720p。

SFU的代码示意

这里用伪代码展示SFU的核心转发逻辑:

// SFU核心转发逻辑(伪代码)
class SFU {
    Map<String, Set<String>> subscriptions; // 订阅关系

    void onMediaPacket(MediaPacket packet, String senderId) {
        // 获取订阅了该发送者的所有接收者
        Set<String> receivers = subscriptions.get(senderId);

        for (String receiverId : receivers) {
            // 检查接收者的带宽和性能
            if (canReceive(receiverId, packet)) {
                // 直接转发,不做任何修改
                forward(packet, receiverId);
            } else {
                // 降级处理:只转发音频或降低分辨率
                downgradeAndForward(packet, receiverId);
            }
        }
    }
}

你看,核心逻辑就这么几行。但实际生产环境要考虑的东西多得多:丢包重传、带宽估计、码率自适应……这些我们后面章节会细讲。

MCU详解:多点控制单元

MCU是更传统的方案。早年的视频会议系统(比如Polycom、Cisco的老设备)基本都是MCU。它的核心思想是:把所有流合成一路

MCU的工作原理

  1. 接收所有参与者的音视频流
  2. 解码所有流
  3. 在服务器端合成一个画面(比如4宫格、9宫格)
  4. 重新编码成一路流,分发给所有人

你想想看,这相当于服务器要同时做N路解码 + 1路合成 + 1路编码。CPU开销非常大。

MCU的典型场景:大型直播、在线教育。比如一个老师对500个学生,老师只需要看到合成后的画面,学生也只需要看老师+几个学生的合成画面。这时候MCU反而更省带宽。

MCU的优缺点

优点

  • 客户端压力小:只需要解码1路流
  • 带宽节省:1路流 vs N路流
  • 布局统一:所有人看到相同画面

缺点

  • 服务器成本高:需要高性能CPU做转码
  • 延迟高:解码→合成→编码,至少增加100ms
  • 灵活性差:不能单独订阅某一路流
  • 扩展性差:一台MCU服务器通常只能支持几十人

我的建议:除非你的场景是「一对多」且客户端设备性能很差,否则优先选SFU。MCU更适合硬件视频会议终端时代,在WebRTC时代已经逐渐被淘汰。

SFU vs MCU:如何选择?

我整理了一个决策树,帮你快速判断:

你的场景是什么?
├── 多人互动会议(3-50人)
│   └── → SFU(推荐)
├── 大型直播(1对多,1000+人)
│   ├── 客户端性能好 → SFU + Simulcast
│   └── 客户端性能差 → MCU
├── 在线教育(1对多,几十人)
│   ├── 需要互动 → SFU
│   └── 纯听课 → MCU
└── 硬件终端兼容(老设备)
    └── → MCU(必须)

SVG架构对比图

下面这张图展示了SFU和MCU的核心差异:

SFU vs MCU 架构对比 SFU 架构 A B C SFU 服务器 A B C 转发,不处理 MCU 架构 A B C MCU 服务器 解码 → 合成 → 编码 合成 所有人看到相同画面

实际项目中的选择

最后说说我的经验。如果你现在要做一个WebRTC项目,我的建议是:

  • 默认选SFU:开源方案有mediasoup、Janus、LiveKit,都很成熟
  • 只有特定场景才考虑MCU:比如老设备兼容、超大规模纯直播
  • 也可以混合使用:SFU做核心转发,MCU做录制或转码

一个小技巧:如果你不确定选哪个,先用SFU。因为SFU可以降级为MCU的功能(通过客户端合成),但MCU无法升级为SFU。我在项目中就吃过这个亏——一开始选了MCU,后来想加个性化布局,发现根本改不了。

好了,这一章我们聊了SFU和MCU的核心区别。下一章我会深入SFU的Simulcast和SVC机制——这两个东西是SFU能灵活适配不同网络的关键。到时候见。


公众号:蓝海资料掘金营,微信deep3321