22、服务端 QoS 策略:SFU 与 MCU 的 QoS 差异、服务端 FEC 与重传、服务端码率转码

聊到服务端的 QoS,很多人第一反应就是「丢包重传」和「FEC」。嗯,这没错,但如果你只盯着客户端看,那就漏掉了最关键的环节——服务端。

我做了这么多年实时通信,有个很深的体会:服务端才是 QoS 的主战场。客户端再努力,网络一差照样卡顿。但服务端不一样,它手里握着整个会议的码流调度权,能做的事情远比客户端多得多。

今天我们就来拆解一下,服务端到底有哪些 QoS 手段,以及 SFU 和 MCU 在这条路上走了哪些不同的路。

SFU 与 MCU:两种架构,两种 QoS 哲学

先搞清楚一个基本问题:SFU 和 MCU 在 QoS 上的差异,本质上是架构差异导致的。

维度 SFU(选择性转发单元) MCU(多点控制单元)
核心逻辑 只转发,不解码 解码 + 混流 + 重新编码
QoS 粒度 按流粒度(每条流独立处理) 按用户粒度(混流后统一处理)
丢包恢复 依赖 NACK / FEC,服务端可介入 服务端可做完整重传 + 转码修复
码率控制 通过 Simulcast / SVC 做选择性丢弃 直接调整编码参数,精度更高
延迟 低(不解码) 高(解码 + 编码引入延迟)
服务器开销 高(每个用户都需要编解码)

说白了,SFU 走的是「轻量转发 + 智能丢弃」路线,MCU 走的是「全量处理 + 精确控制」路线。我个人更倾向于 SFU,因为它更灵活,也更适合大规模部署。但 MCU 在某些场景下确实有不可替代的优势,比如混流录制。

核心差异一句话总结:SFU 在传输层做 QoS,MCU 在媒体层做 QoS。前者靠策略,后者靠算力。

服务端 FEC 与重传:谁该干活?

客户端也有 FEC 和重传,那服务端为什么还要做?

原因很简单:客户端之间的网络路径,服务端不一定能控制。比如 A 和 B 都在弱网环境下,客户端之间的重传可能来回绕路,延迟爆炸。但服务端如果介入,可以在服务器和客户端之间建立更短的路径,重传效率高得多。

服务端 FEC(前向纠错)

FEC 的原理我不多讲了,就是发送冗余包,让接收端能直接恢复丢包。服务端做 FEC 和客户端做 FEC 有什么区别?

  • 客户端 FEC:发送端自己算冗余,接收端自己恢复。问题是发送端不知道接收端的网络状况,冗余度很难调。
  • 服务端 FEC:服务端作为中转,可以根据每个接收端的反馈动态调整冗余度。比如 A 网络好,不加 FEC;B 网络差,加 20% 冗余。

我在项目中遇到过一种情况:客户端 FEC 开太高,导致带宽被冗余包占满,视频质量反而下降。后来改成服务端动态 FEC,根据丢包率实时调整冗余比例,效果好了很多。

我的建议:服务端 FEC 不要对所有流一视同仁。按接收端丢包率分级,丢包率 < 5% 不加 FEC,5%-15% 加 10% 冗余,> 15% 加 20% 冗余。再高就别加 FEC 了,直接降码率。

服务端重传(NACK)

重传这件事,客户端做和服务端做,最大的区别在于缓存策略

客户端重传,缓存的是自己发送的包。服务端重传,缓存的是所有经过它的包。这意味着什么?

  • 如果 A 发给 B 的包丢了,B 向 A 请求重传,A 可能已经清掉了缓存(比如 200ms 前的包)。
  • 但如果服务端也缓存了一份,B 可以直接向服务端请求重传,服务端的缓存时间可以设得更长(比如 1-2 秒)。

我曾经踩过一个坑:客户端重传缓存设太短,导致丢包后重传失败,画面直接卡死。后来在服务端加了一层重传缓存,丢包恢复率从 70% 提升到了 95% 以上。

注意:服务端重传缓存不是越大越好。缓存越大,内存占用越高,而且延迟也会增加。我一般建议缓存 500ms-1s 的数据,超过这个时间的包直接丢弃,因为重传回来也来不及渲染了。

服务端码率转码:最后的杀手锏

前面说的 FEC 和重传,都是在「不改变码流内容」的前提下做恢复。但如果网络实在太差,丢包率超过 30%,FEC 和重传都救不了。这时候就需要码率转码了。

码率转码,说白了就是服务端把高码率的视频流,重新编码成低码率的流,再发给接收端。这样接收端需要的带宽更少,丢包概率自然降低。

SFU 怎么做码率转码?

SFU 本身不解码,所以它不能直接做转码。但 SFU 可以利用 Simulcast 或 SVC 来实现「伪转码」:

  • Simulcast:发送端同时发送多路不同分辨率的流(比如 720p、360p、180p)。SFU 根据接收端的网络状况,选择合适的一路转发。
  • SVC:发送端编码时分层(基础层 + 增强层)。SFU 可以丢弃增强层,只转发基础层,相当于降低了码率。

这两种方式都不需要服务端解码,开销很低。但缺点也很明显:发送端必须支持 Simulcast 或 SVC,而且码率调整的粒度有限。

MCU 怎么做码率转码?

MCU 就简单粗暴了:它本来就要解码,所以直接重新编码就行。MCU 可以做到:

  • 精确控制输出码率(比如从 2Mbps 降到 500kbps)
  • 动态调整分辨率、帧率、编码参数
  • 甚至可以做转码降噪(比如把 H.264 转成 VP8)

但代价也很高:每个接收端都需要一路独立的编码器,服务器 CPU/GPU 开销巨大。我见过一个 50 人的 MCU 会议,服务器直接跑满了 32 核 CPU。

我的经验:如果服务器资源充足,MCU 的码率转码效果确实最好。但大多数场景下,我更推荐 SFU + Simulcast 的方案,性价比高得多。只有在录制、转码等必须重新编码的场景,才上 MCU。

知识体系总览

下面这张图,我把服务端 QoS 的核心策略和它们之间的关系梳理了一下。你可以把它当作本章的思维导图。

服务端 QoS 策略总览 服务端 QoS SFU vs MCU 架构差异 FEC 与 重传 码率转码 按流粒度 QoS Simulcast/SVC 低延迟 按用户粒度 QoS 精确码率控制 高服务器开销 动态冗余调整 服务端缓存重传 分级丢包恢复 Simulcast 选流 SVC 分层丢弃 MCU 重新编码 核心原则:传输层保底 + 媒体层兜底

避坑指南

最后分享几个我踩过的坑,希望能帮你少走弯路:

  • 不要迷信 FEC:我曾经在一个项目中把 FEC 冗余开到 50%,结果丢包率没降多少,带宽反而被吃光了。FEC 适合低丢包率场景(< 10%),丢包率高了还是得靠重传或降码率。
  • 服务端重传缓存要按流独立管理:不同流的延迟敏感度不一样。音频流的缓存可以短一点(200ms),视频流可以长一点(1s)。混在一起管理,要么浪费内存,要么恢复不及时。
  • Simulcast 不是银弹:Simulcast 需要发送端编码多路流,对发送端的 CPU 和带宽都有要求。如果发送端是手机,Simulcast 可能反而导致编码延迟增加。这时候 SVC 是更好的选择。
  • MCU 转码要注意同步:MCU 解码再编码会引入几十毫秒的延迟,如果混流时音频和视频不同步,用户体验会很差。我一般建议 MCU 场景下,音频走 SFU 直传,视频走 MCU 转码,避免音频也被延迟。

好了,服务端 QoS 的策略就聊到这里。记住一句话:没有万能的策略,只有合适的组合。SFU 和 MCU 各有优劣,FEC 和重传各有适用场景,码率转码是最后的兜底手段。具体怎么选,取决于你的业务场景和服务器资源。


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