JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
  1. Main page
  2. Network
  3. Main content

浅谈基于SFU实现一对一效果

2024年11月7日 79hotness 0likes 0comments

基于SFU架构的视频会议系统中,Simulcast是最主流的带宽自适应方案。发布端(Publisher)同时编码并发送多路不同分辨率的流(通常为小、中、大三路),订阅端(Subscriber)则根据自身网络带宽、设备性能、窗口大小等因素,选择订阅最合适的单路流。这种设计发布端与订阅端互不干扰:

  • 发布端仅受自身上行带宽和编码负载影响
  • 订阅端仅受自身下行带宽,解码能力,显示窗口影响


但在实际生产环境中,某些核心场景却需要订阅端能够“反向影响”发布端,即实现backpressure(反压)机制。

反压需求场景

按需推流

当会议中所有订阅端都处于小窗口显示(如宫格数较多、缩略图模式)时,大家只会订阅小流。此时发布端若仍持续推送大流,就会造成巨大的上行带宽浪费和服务器转发压力。理想状态是:订阅端集体选择小流 → SFU 通知发布端自动降档,只推小流即可。

SFU模拟点对点(P2P)通话

用SFU统一实现1对1通话(便于后续扩展多人)。此时必须达到原生P2P(ICE直连)的体验。

  • 订阅端网络恶化时,不能仅靠切换Simulcast层(因为只有一层流),而应直接让发布端降低编码码率/分辨率
  • 订阅端网络恢复后,发布端也要快速回升

在传统Simulcast中做不到这样的“端到端拥塞控制”。

SFU如何实现订阅端反压

核心思路:在SFU内部为每个发布源(Source)和每个订阅接收器(Sink) 建立反馈通道,让订阅客户端的带宽估计结果能够传递到发布客户端。
下面是实现原理图:

  • 发布客户端 → RTP → SFU Source(发布源)
  • SFU Sink(订阅接收器)收到订阅端发来的 Transport-CC报文,进行下行带宽估计
  • Sink通过onFeedback接口将估计带宽值传递给对应的Source
  • Source封装REMB(Receiver Estimated Maximum Bitrate)RTCP报文,传回到发布客户端
  • 发布客户端收到REMB后,强制限制自身带宽估计值

这样就实现了订阅端 → SFU → 发布端的完整反压闭环。

REMB RTCP报文复用

WebRTC早期就内置了REMB RTCP,用在最早的接收端带宽估计中,接收端的带宽估计就是通过REMB反馈到发布端。虽然现在是Transport-CC + Sendside BWE,但REMB仍然被支持。这里可以看下REMB报文格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
//
//     0                   1                   2                   3
//     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//    |V=2|P| FMT=15  |   PT=206      |             length            |
//    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//  0 |                  SSRC of packet sender                        |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  4 |                       Unused = 0                              |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  8 |  Unique identifier 'R' 'E' 'M' 'B'                            |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 12 |  Num SSRC     | BR Exp    |  BR Mantissa                      |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 16 |   SSRC feedback                                               |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//    :  ...            

对于SFU,带宽反馈处理只需在 Source 侧调用:

1
2
3
4
5
6
7
8
9
10
11
// Sink带宽估计后调用
void Sink::OnBandwidthEstimate(DataRate estimate) {
    source_->OnFeedback(estimate);  // 通知对应的的Source
}
 
// Source收到后下发REMB
void Source::OnFeedback(DataRate bandwidth) {
    if (publisher_session_) {
        publisher_session_->SendRtcpREMB(bandwidth);
    }
}

发布客户端中WebRTC收到REMB后的处理如下:

C++
1
2
3
4
5
6
// Call when we receive a RTCP message with TMMBR or REMB.
void SendSideBandwidthEstimation::UpdateReceiverEstimate(Timestamp at_time,
                                                         DataRate bandwidth) {
  receiver_limit_ = bandwidth.IsZero() ? DataRate::PlusInfinity() : bandwidth;
  ApplyTargetLimits(at_time);
}

至此我们完成初步的反压实现。

遗留问题:弱网解除后带宽恢复速度慢

前面实现后还有个问题,就是订阅端弱网恢复后,恢复之前码率较慢。原因如下:

  • 订阅端之前带宽差 → SFU反馈低REMB → 发布端码率被压得很低
  • 订阅端网络恢复 → 其BWE想提升,但实际收到的码率仍然很低(受发布端限制)
  • 订阅端BWE探测不到更高带宽 → 继续反馈低REMB → 发布端无法提升 → 形成“死循环”

这就像“受制于人”,恢复速度远慢于原生的P2P实现。

这时候我们可以在SFU的Sink(下行)侧中,主动注入探测流量,也就是引入探测(Padding)包。让订阅端能够获得额外码率进行更大带宽探测,打破死循环,加快恢复到之前码率。

总结

通过以上机制,SFU不仅保留了Simulcast的灵活性,还具备了端到端拥塞控制能力,让视频会议在复杂网络环境下也能提供接近原生P2P的流畅体验。

This article is licensed with Creative Commons Attribution-NonCommercial-No Derivatives 4.0 International License
Tag: WebRTC 网络
Last updated:2026年3月14日

Jeff

管理员——代码为剑,如痴如醉

Tip the author Like
< Last article

Comments

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
Cancel

This site uses Akismet to reduce spam. Learn how your comment data is processed.

文章目录
  • 反压需求场景
    • 按需推流
    • SFU模拟点对点(P2P)通话
  • SFU如何实现订阅端反压
    • REMB RTCP报文复用
  • 遗留问题:弱网解除后带宽恢复速度慢
  • 总结
Related Posts
  • WebRTC音视频传输基础:NAT穿透
  • WebRTC研究:统计参数之往返时延
  • WebRTC研究:Transport-cc之RTP及RTCP
  • WebRTC研究:丢包判断
  • WebRTC研究:RTP中的序列号以及时间戳比较
Categories

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang