WebRTC Simulcast介绍

原文地址👇

https://blog.livekit.io/an-introduction-to-webrtc-simulcast-6c5f1f6402eb/

你想知道的关于Simulcast的一切

Simulcast是WebRTC中最酷的功能之一,它允许WebRTC会议在参与者网络连接不可预测的情况下进行扩展。在这篇文章中,我们将深入探讨Simulcast的工作原理,以及它如何与像LiveKit这样的SFU协作,以支持更大规模的WebRTC会议。

“慢速”用户(网速慢)的挑战

Selective Forwarding Units(SFU)已经成为基于WebRTC的会议的主流架构。它们的作用是将一个用户的数据转发给房间中的其他用户,从而显著减少每个用户必须发送的数据量。近年来由于SFU扩展相对简单,获得了相当大的普及。由于它们不需要对媒体进行编码/解码,因此转发数据通常只需要很少的CPU开销。

虽然直接转发接收到的流使得架构和程序变得简单,但真实的网络条件提出了一些挑战。具体来说,并非每个人都拥有足够快的互联网连接来接收其他人发布的流。从“慢速”用户加入会议的那一刻起,这个问题就变得非常明显。

用户C将收到断断续续的流

由于慢速用户的下行带宽不足以获取其他用户正在发送的高质量流,所以他们在接收端会遭受高数据包丢失,导致画面质量不连贯或出现黑屏/空白帧。随着下游带宽达到饱和,拥塞也会影响用户上传自己视频的能力。

更糟糕的是,慢速用户的WebRTC客户端将不断向其他发布参与者发送PLI(画面丢失指示)消息(通过SFU),因为它无法接收足够的数据包来渲染帧。当其他WebRTC客户端看到PLI数据包时,它们会通过生成新的关键帧来响应,这些关键帧需要发送给每个人,增加整个会话的带宽需求。增加的带宽需求可能触发级联效应,当它超过其他参与者的带宽限制时。

在一个大量人员的会议中,房间中有人连接欠佳的可能性会增加。每个会议最终都会遇到这个慢速用户的问题。所以,为了确保平滑和高质量的传输,我们有三个选择:

  • 使用可缩放编解码器,如VP9或AV1
  • 降低每个人的数据流比特率,以免超载慢速用户(即最低公共比特率)
  • 向参与者发送独立的数据流,以适应每个用户的可用带宽

可伸缩视频编解码器

值得一提的是一些较新的视频编解码器及其权衡。VP9和AV1都内置了可伸缩性:它们以一种可以适应多个目标比特率的方式进行编码。但是,它们确实存在一些缺点(截至2021年8月):

  • VP9不支持Safari,且CPU密集型更高
  • AV1仅支持Chrome

虽然未来前景光明,但如今,这两种编解码器在动态比特率方面都不是实际的解决方案。

Simulcast登场

Simulcast允许WebRTC客户端发布同一源轨道的多个版本,具有不同的编码(即空间层)。在LiveKit中,参与者发布高分辨率、中分辨率和低分辨率版本的同一视频,这些视频以不同的比特率进行编码。

Simulcast旨在与SFU一起使用,其中SFU接收跟踪的所有三层,并对每个订阅者选择转发哪一层。

SFU选择向User C发送低分辨率流

从订阅者的角度来看,Simulcast是不可见的。WebRTC轨道设计时就支持动态调整分辨率。对于订阅者来说,这使得SFU可以在其带宽改变时切换到不同的层,同时保持连续的视频流无中断。

这是否意味着发布者需要发送更多数据?是的。但是,较低分辨率的层消耗的带宽远少于高质量版本。例如:

  • 原始/高分辨率:1280 x 720 @ 2.5Mbps
  • 中分辨率:640 x 360 @ 400Kbps
  • 低分辨率:320 x 180 @ 125Kbps

使用Simulcast,发布者只需要大约17%的额外带宽就可以发布所有三层。

通过更高级的反馈机制,带宽使用量还可以大大降低。如果某人的视频在接收端严格只呈现为缩略图,为什么还要发送720p层呢?每个订阅者都可以通知SFU它实际需要的层。

看一下Zoom的网络统计数据,你会发现他们管理这一点做得非常好。当参与者不是主讲人,并以缩略图的形式显示给其他人时,Zoom客户端只发送320x180层。

空间与时间可伸缩性

我们介绍了空间层,那么时间可伸缩性又是什么呢?本质上,时间可伸缩性是通过动态降低流的帧速率来降低流比特率的能力。

非可伸缩视频流中的帧,每个帧引用前一帧 

Untitled

这个想法很简单,但复杂性在于视频的编码方式 - 流包含主要是delta帧,这些帧依赖于之前的帧。如果解码器需要对被跳过的帧应用delta,它无法渲染后续帧。 为了使时间可伸缩性能够工作,编码器需要提前规划帧依赖性。

具有两个时间层的可伸缩流中的帧 

Untitled

VP8支持时间可伸缩性,当使用Simulcast时,浏览器会自动启用它。在上面的图中,我们看到一个具有两个时间层的启用了时间可伸缩性的流。我们使用TID来表示时间层:基本层具有TID 0,增强层具有TID 1。基本层上的帧仅引用其他基本层帧。 对于带宽有限的订阅者,我们可以跳过发送所有TID 1的帧,仅转发TID 0的帧。 这有效地将带宽需求降低了约50%,同时保持原始流的质量。 时间可伸缩性更适合内容如屏幕共享,其中清晰度大于FPS。


SFU中发生了什么?

为了支持Simulcast,SFU需要执行一些额外的步骤来完成这种神奇的操作。让我们继续看下面的内容。

重写序列号和时间戳

每个RTP数据包都包含一个序列号,指示流中其顺序,以及时间戳指示何时应播放帧。 WebRTC客户端依靠序列号来检测丢包情况,以及是否应该重新请求(NACK)该数据包。 当客户端收到序列号存在间隙的情况时,它会假设数据包在传输中丢失了。

对于Simulcast的轨道,每个层都作为一个独立的轨道发送,并带有自己的序列号集。 当SFU在层之间切换时,序列号中会有间隙。 对于时间层也是如此,当跳过某些帧时,传出序列号中会有跳跃。

为了补偿这一点,SFU需要跟踪每个订阅者的序列号,并重写每个数据包的序列号。 即使在重传丢失数据包时也需要维护此映射。(译者:也就是说对于订阅客户端来说接收到的rtp seq序号必须是连续的,而不会随着切换不通质量的流seq发生不连续的情况。)

带宽估计/拥塞检测

那么,我们如何知道要为每个订阅者发送哪个空间和时间层呢?理想情况下,它应该是其连接可以处理的最高质量流。 但如何确定呢?

事实证明WebRTC通过RTCP数据包内置了一些简洁的反馈机制:​​​​​

  • 接收者报告(RR):接收者定期发送报告以指示丢包率和抖动等信息
  • 传输范围拥塞控制(TWCC):允许发送方检测接收端的拥塞
  • 接收端估计最大比特率(REMB):接收端定期发送报告,指示估计的可用带宽。 (注意:如今TWCC优于REMB)

SFU接收反馈,并使用拥塞检测算法来估计可用带宽量。我们必须将码率维持在信道的可用带宽内,以避免拥塞。当拥塞发生时,我们将看到数据包丢失量增加,这将导致视频和音频冻结和失真。

跟踪订阅者层(Keep track of subscriber layers)

对于每个订阅者和轨道组合(track combination),SFU需要跟踪:

  • 订阅者希望哪个空间层?例如,如果客户端只需要320x180的流,那么我们就不应该发送任何更码率更高的流。
  • 订阅者的带宽允许哪个空间和时间层?

然后根据以下规则为每个订阅者做出决定:min(desired, allowed)(译者:也就是说sfu应该先得到观众期望的码率,然后再和允许发送的最大码率的值进行比较,取二者的最小值。)


处理发布者约束(Handling publisher constraints

到目前为止,我们已经介绍了如何处理订阅者的带宽限制。如果发布者存在上行带宽限制怎么办?如果发布者具有有限的上行带宽,则无法成功发布所有三个空间层。

浏览器处理这种情况的行为相当不错。 当带宽有限且启用了Simulcast时,WebRTC将禁用高分辨率层,直到它可以在不明显丢包的情况下发送流。您可以通过WebRTC统计信息观察到这一点,其中qualityLimitationReason设置为bandwidth。 类似地,如果发布者的处理器无法足够快地编码三个独立的层,则qualityLimitationReason设置为cpu。

chrome://webrtc-internals

但是,当浏览器决定停止发送层时不会提前通知SFU。 任何订阅终止层的订阅者都将停止接收新数据包,这会导致观众看到静止的画面。(译者:换句话说,如果浏览器在没有任何征兆的情况下停止上传某一个清晰度的流,那么正在订阅这个清晰度的观众则会看到画面卡死。)

这种情况这是不可取的, 将订阅者置于可用的较低分辨率层上会提供更好的体验。您可能已经猜到,这又是一个SFU需要解决的问题。 SFU需要监视每个层上传入数据包的中断情况, 如果检测到某个层上的数据中断,则会将该层标记为不可用,并将订阅者移动到替代层。您可以在StreamTracker中看到LiveKit如何处理此问题。

浏览器行为

我们需要特别注意当浏览器遇到带宽瓶颈的情况。当浏览器将某个清晰度的层禁用后,浏览器将在几秒后尝试重新启用它,只是为了在发现带宽没有改善时再次禁用它。 此波动在webrtc-internals图表中非常明显。 您可以使用MacOS中的网络链接条件仿真器模拟低带宽链接。

Untitled

framesEncoded/s和framesSent/s都呈现波动

通过测试我们已经发现一旦浏览器开始波动,即使带宽恢复后,它也会保持在这种状态。 这一点很出乎意外,我们推测可能是由于SFU或Google的WebRTC实现中的带宽估计逻辑错误造成的。 需要进一步的研究来查明根本原因。

客户端层管理

为了确保网络条件改善后视频质量可以恢复,我们在客户端引入了对simulcast编码的自定义管理。 这利用了WebRTC暴露的一些接口:

  • 通过RTCRtpSendParameters.encodings获取特定轨道的编码列表
  • 通过设置RTCRtpEncodingParameters.active控制层是否活动。 将其设置为false时,浏览器将停止发送该层。

有了这些接口,客户端可以监控当前带宽。 在检测到限制时,客户端可以完全暂停较高码率的视频层(layer),并在更长的回退后尝试重新启用和发送(译者:推测是根据服务器端的反馈决定是否恢复被禁的视频层。我认为这种恢复操作是很谨慎的,应该是从算法角度看可以恢复之后再等待很长时间后才可以恢复,也就是调用RTCRtpEncodingParameters.active=true)。 我们发现这种方法可以解决波动行为,允许一致的质量恢复。

如果您仍在阅读,希望您发现这篇文章很有用。 虽然Simulcast增加了WebRTC实现的复杂性,但它对于提供高质量的多用户会议来说是必要的。

如果您正在寻找支持Simulcast的WebRTC会议平台,请试试LiveKit!

感谢Raja、Orlando和Russ审阅了本文的草稿。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/45023.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Databend 开源周报第 103 期

Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 创建网络策略 …

Centos7 扩容(LVM 和非 LVM)

一、磁盘扩容方式 CentOS 系统的磁盘扩容可以分为两种方式:LVM 管理和非 LVM 管理。 LVM 管理的分区和传统分区方式是可以共存的。在同一个系统中,你可以同时使用 LVM 管理的分区和传统分区。 例如,在 CentOS 系统中,你可以选择将…

第一次编程测试(分频器)

一,分频器 定义 分频器(Divider)是一种电子电路或设备,用于将输入信号的频率降低到较低的频率。它常用于数字系统、通信系统和计时应用中。原理 整数分频器使用计数器来实现频率的降低。计数器根据输入信号的边沿触发进行计数&am…

(三)RabbitMQ七种模式介绍与代码演示

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 七种模式介绍与代码演示 文章目录 七种模式介绍与代码演示四大交换机四种交换机介绍 工作模式简单模式&#xff08;Hello World&#xff09;工作队列模式&#xff08;Work queues&#xff09;订阅模式&#xff08;Publis…

macOS Big Sur 11.7.9 (20G1426) 正式版 ISO、PKG、DMG、IPSW 下载

macOS Big Sur 11.7.9 (20G1426) 正式版 ISO、PKG、DMG、IPSW 下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Window…

【FPGA/D6】

2023年7月25日 VGA控制器 视频23notecodetb 条件编译error时序图保存与读取&#xff1f;&#xff1f;RGBTFT显示屏 视频24PPI未分配的引脚或电平的解决方法 VGA控制器 视频23 note MCU单片机 VGA显示实时采集图像 行消隐/行同步/场同步/场消隐 CRT&#xff1a;阴极射线管 640…

94.qt qml-分页Table表格组件

在我们之前学习了87.qt qml-分页组件控件(支持设置任意折叠页数等)_qt分页控件_诺谦的博客-CSDN博客 然后我们又学习了Table实现,所以本章实现一个分页Table表格组件,配合分页控件, 模拟请求服务器数据来实现数据分解效果,因为一般使用分页的时候,一般都是分页请求,避免数…

Android TelephonyManager双卡获取数据开启状态异常的可能原因

背景 应用内不指定subId获取数据状态可能会错误&#xff0c;因为可能拿到voice的能力&#xff0c;而非data。 代码逻辑 1、通过TelephonyManager的isDataEnabled()没有指定subId时&#xff0c;调用内部方法isDataEnabledForReason&#xff0c;传入getId()参数以指定subid&am…

Hadoop——Hive运行环境搭建

Windows&#xff1a;10 JDK&#xff1a;1.8 Apache Hadoop&#xff1a;2.7.0 Apache Hive&#xff1a;2.1.1 Apache Hive src&#xff1a;1.2.2 MySQL&#xff1a;5.7 1、下载 Hadoop搭建 Apache Hive 2.1.1&#xff1a;https://archive.a…

【ArcGIS Pro微课1000例】0029:绘制全球海洋波纹荡漾效果图

本文讲解ArcGIS Pro3.0中,基于全球航洋面状矢量数据,绘制震撼全球海洋波纹荡漾效果图。 文章目录 一、效果预览二、效果制作三、参数详解一、效果预览 绘制好的海水波纹荡漾效果图如下: 下面我们来学习绘制过程。 二、效果制作 波纹荡漾效果需要在全局或者局部场景中制作…

【JVM】浅看JVM的运行流程和垃圾回收

1.JVM是什么 JVM&#xff08; Java Virtual Machine&#xff09;就是Java虚拟机。 Java的程序都运行在JVM中。 2.JVM的运行流程 JVM的执行流程&#xff1a; 程序在执行之前先要把java代码转换成字节码&#xff08;class文件&#xff09;&#xff0c;JVM 首先需要把字节码通过…

macbook 软件iMovie for Mac(专业视频剪辑工具)中文版

iMovie mac中文版是一款针对Mac平台量身定做的视频编辑工具&#xff0c;软件凭借流线型设计和直观的编辑功能&#xff0c;可以让您感受前所未有的方式制作好莱坞风格的预告片和精美电影&#xff0c;并且还可以浏览视频资料库&#xff0c;快速共享挚爱瞬间&#xff0c;创建精美的…

结构型设计模式之装饰器模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…

如何在Windows上恢复已删除的文件?

大多数人在无意中删除了一些重要文件后无法恢复。这些文件被暂时删除&#xff0c;直到我们清空回收站才会消失。你可以通过右键单击回收站中的文件并选择还原选项来轻松恢复这些文件。但是&#xff0c;如果你清理回收站删除了文件怎么办&#xff1f;或者不小心使用Shift Delet…

SpringCloud学习路线(10)——分布式搜索ElasticSeach基础

一、初识ES &#xff08;一&#xff09;概念&#xff1a; ES是一款开源搜索引擎&#xff0c;结合数据可视化【Kibana】、数据抓取【Logstash、Beats】共同集成为ELK&#xff08;Elastic Stack&#xff09;&#xff0c;ELK被广泛应用于日志数据分析和实时监控等领域&#xff0…

【数据挖掘】将NLP技术引入到股市分析

一、说明 在交易中实施的机器学习模型通常根据历史股票价格和其他定量数据进行训练&#xff0c;以预测未来的股票价格。但是&#xff0c;自然语言处理&#xff08;NLP&#xff09;使我们能够分析财务文档&#xff0c;例如10-k表格&#xff0c;以预测股票走势。 二、对自然语言处…

2023年Q2京东环境电器市场数据分析(京东数据产品)

今年Q2&#xff0c;环境电器市场中不少类目表现亮眼&#xff0c;尤其是以净水器、空气净化器、除湿机等为代表的环境健康电器。此外&#xff0c;像冷风扇这类具有强季节性特征的电器也呈现出比较好的增长态势。 接下来&#xff0c;结合具体数据我们一起来分析Q2环境电器市场中…

【已解决】jupyter notebook里已经安装了第三方库,还是提示导入失败

在jupyter notebook中运行Python代码&#xff0c;明明已经安装了第三方库&#xff0c;还是提示导入失败。 以导入pandas库为例&#xff0c;其他库同理&#xff1a; 报错代码&#xff1a; import pandas报错原因&#xff1a; 电脑上存在多个python运行环境&#xff08;比如&a…

JavaEE——Spring中存取Bean的注解

目录 一、存储Bean对象 1、定义 2、存储方式 &#xff08;1&#xff09;、类注解 【1】、Controller&#xff08;控制器存储&#xff09; 【2】、Service&#xff08;服务存储&#xff09; 【3】、Repository&#xff08;仓库存储&#xff09; 【4】、Component&#xf…

[JAVAee]线程安全

目录 线程安全的理解 线程不安全的原因 ①非原子性 ②可见性 ③代码重排序 体会何为不安全的线程 保证线程安全 一个代码在多线程的环境下就很容易出现错误. 线程安全的理解 线程安全是什么呢?通俗的来讲,线程安全就是在多线程的环境下,代码的结果是符合我们预期的,就…