WebRTC 系列之视频辅流

news2024/9/23 3:28:16

WebRTC 中的 SDP 支持两种方案: PlanB 方案 和 Unified Plan 方案。早期我们使用多PeerConnection的 Plan B 方案中只支持一条视频流发送,这条视频流,我们称之为”主流”。目前我们使用单 PeerConnection 的 Unified Plan 方案,新增一条视频辅流,何为视频”辅流”?视频辅流是指第二条视频流,一般用于屏幕共享。

1、 需求背景


随着业务的发展,一路视频流满足不了更多实际业务场景的需求,例如在多人视频聊天、网易会议以及其他在线教育场景下,需要同时发送两路视频流:一路是摄像头流,另一路是屏幕共享流。

但是,目前使用 SDK 分享屏幕时,采用的是从摄像头采集通道进行屏幕分享。在该方案下,分享者只有一路上行视频流,该场景中要么上行摄像头画面,要么上行屏幕画面,两者是互斥的。

除非实例一个新的 SDK 专门采集并发送屏幕画面,但实例两个 SDK 的方案在业务层处理起来十分麻烦且会存在许多问题,例如如何处理两个流间的关系等。

在 WebRTC 场景中,还存在一种可以单独为屏幕分享开启一路上行视频流的方案,并称之为“辅流(Substream)”。辅流分享即共享者同时发布摄像头画面和屏幕画面两路画面。

另外,有了这个辅流的通道,当设备为新版本 iPhone(新版本 iPhone 具有同时开启前后摄像头的能力)时,也为支持前后2路摄像头发送视频数据奠定了基础。

2、 技术背景


前期 SDK 的架构设计是一个多 PeerConnection 的模型,即:一个 PeerConnection 对应一路音视频流。随着新的 SDP(Session Description Protocol)格式(UnifyPlan)的推出和支持,一个 PeerConnection 可以对应多路音视频流,即单 PeerConnection 模型,即基于单 PC 的架构,允许创建多个 Transceiver,用于发送多条视频流

3、 技术实现


目前视频流主要分为三类:Camera 流、屏幕共享流、自定义输入视频流,分别有不同属性:

  1. 将 Camera 流作为主流,支持 Simulcast;

  1. 将自定义视频输入(非屏幕共享)作为主流,不支持 Simulcast;

  1. 将屏幕共享作为辅流,不支持 Simulcast,有单独的屏幕共享编码策略;

由于 iOS 屏幕共享的特殊性,其需要通过自定义视频输入的方式来获取视频数据,因此存在如下图所示的流程图:

综上所述:iOS 的自定义输入既可以使用主流的通道发送视频(非屏幕共享),也可以使用辅流的通道发送视频(屏幕共享)。

如果是其他平台,例如 Mac、Win、Aos 等,则会相对简单,摄像头数据和屏幕共享的数据都来自于 SDK 内部,外部自定义视频输入的数据才来自于外部。

3.1 关键类图

上述提到的单 PC 架构,目前会有2个 RtpTransceiver,一个是 AudioTransceiver,一个是 VideoTransceiver,而辅流的屏幕共享会在新增一个 RtpTransceiver。一个 VideoRtpSender 会包含一个 VideoMediaChannel。

3.2 辅流改动

实现辅流需要对不同层面都做一些调整以及重构,具体如下:

  1. 信令层面需要支持多路视频流,使用 mediaType 用于区分上述的 Camera 流(Video)、屏幕共享流(ScreenShare)、自定义视频输入流(externalVideo);

  1. 重构跨平台层的 Capture 和 Source 的管理;

  1. 重构用户和渲染画布的管理,从一个 UID 对应一个 render,过渡到一个 UID 的 sourceId 对应一个 render,每个 UID 可能会包含2个 sourceId;

  1. 互动直播的服务器推流和录制需要支持主流和辅流的合流录制;

  1. 主流和辅流的拥塞控制方案的落地;

  1. 主流和辅流的码率分配方案的落地;

  1. 主流和辅流的编码器性能优化;

  1. PacedSender 发送策略、音画同步等方案的调整;

  1. 服务器 Qos 下行码率的分配方案的调整;

  1. 辅流相关的统计数据的汇总;

下面介绍在整个过程中,比较重要的几个技术点的实现。

3.3 带宽分配

在弱网情况下,需要视频辅流的时候,我们会优先把码率分配给音频流,其次是辅流,最后再分配给主流,整体策略为保辅流

带宽分配的主要流程如下:

  1. WebRTC 的拥塞控制算法 GCC(下文简称 CC) 评估出来的总带宽分配会分给音频流、主流、辅流;

  1. 主流内部再由 Simulcast 模块分配大小流的码率,不开 Simulcast 时就直接给大流;

具体过程如图所示:

辅流会在上图的基础上再新增一个 VideoSendStream。

3.4 码率分配

目前关于码率分配的流程如下图所示,概括起来有一下几步:

  1. CC 的码率通过 transport controller 传递到 Call 中;

  1. 然后经过 BitrateAllocator 分配到各个注册的流中 (目前就是视频模块);

  1. 视频模块拿到分配的码率,分配给 fec 和重传,剩下来的分配给 video encoder bitrate;

  1. 视频编码器模块拿到 video encoder bitrate,按照我们的策略,分配给大流、小流使用;

3.5 拥塞控制

为了实现视频辅流的功能,我们需要对拥塞控制进行相关的改动,主要通过以下四个方面的改动来实现:

SDP 信令改动

按照 RFC 2327(https://tools.ietf.org/html/rfc2327),使用 "b=<modifier>:<bandwidth-value>" 的方式来指定建议带宽,有两种 modifier(修饰符):

  • AS:单一媒体带宽;

  • CT:会话总带宽,表示所有媒体的总带宽;

目前 SDK 使用 b=AS: 的方式指定摄像头码流或屏幕共享码流的建议带宽,并把这个值作为 CC 模块的估计值上限。

新的需求要求在同一会话中,可同时发送摄像头码流和屏幕共享码流,因此应把两路媒体的建议带宽值相加得到整个会话的建议带宽值,作为 CC 模块的估计值上限。

WebRTC 支持 b=AS: 方式(单路媒体),在 WebRTC 内部对多路媒体进行相加处理即可满足需求,而 WebRTC 目前不支持 b=CT: 方式,所以建议使用 b=AS: 方式,改动相对较少。

CC 总码率更新策略

Pub 码流能力更新,通过 SDP 方式 (b=AS:) 同步设置"最大带宽"到 CC 模块,当新增一路媒体流时,通过启动 probe 快速探测的方式,迅速上探到可用带宽:

快速带宽评估

突然增加一路媒体流时,需要能够很快上探到真实带宽值,使用 probe 快速探测算法实现这一目标:

  • 如果探测成功,CC 估计值迅速收敛,在带宽充足场景中收敛为 CC 上限,带宽受限场景中为真实带宽;

  • 如果探测失败(如高丢包率场景),CC 估计值缓慢收敛,在带宽充足场景中最终收敛为 CC 上限, 带宽受限场景中为真实带宽;

Paced Sender 处理

  • 辅流与主流的视频大小流的发送优先级一致,所有视频媒体数据,使用预算和 pacing multiplier 的方式做平滑发送处理;

  • 增加一个视频码流类型,kVideoSubStream = 3,与主流的大小流视频数据区分开来;

  • Probe 快速探测期间,当编码数据不足的情况下,发送 padding 数据弥补,以保证发送码率满足要求;

下图为实际进行码率分配测试的结果展示:

3.6 统计上报

带宽的统计上报分为两个部分,分别是从 MediaInfo 获取以及 Bweinfo 获取。

1、发送端和接收端 MediaInfo 获取

当前 SDK 的带宽估计从 MediaInfo 获取逻辑为:

  • 遍历当前所有 transceiver,获取每个 transceiver 的 video_channel 和 voice_channel,从而获取到 video_media_channel 和 voice_media_channel;

  • 根据 media_channel 的 getstats 获取当前 channel 的 MediaInfo;

  • 将获取的 MediaInfo 放在 vertor media_infos 中,便于上报;

主流和辅流同时发送场景,只是增加了一个 transceiver,因此此逻辑适用于主流和辅流同时发送的场景,如下图:

2、带宽估计信息获取

当前 SDK 的带宽估计从 Bweinfo 获取逻辑:

  • 获取 gcc、probe 探测等表示总体带宽信息;

  • 获取每个 transceiver 的 voiceChanel 和 videoChannel 相关的带宽估计信息(类似于 MediaInfo 的获取);

主流和辅流同时发送的场景只是增加了 transceiver,因此此逻辑适用主流加辅流同时发送场景,如下图:

4、 总结


以上就是关于 WebRTC 中视频辅流的分享,主要从业务需求出发,通过技术背景以及关键技术类图,详细分享了关于视频辅流的技术实现。也欢迎留言与我们交流关于 WebRTC 以及音视频相关技术。

原文 https://zhuanlan.zhihu.com/p/338828532

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二叉树——把二叉搜索树转换为累加树

538. 把二叉搜索树转换为累加树 链接 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xf…

春天到了,来一场 VoxEdit 创作大赛吧!

春天的气息扑面而来&#xff0c;这是让你尽情绽放创造力的最佳时机&#xff01;我们将以「春天」为主题来一场 VoxEdit 大赛。在这里&#xff0c;你可以展示你的才华并赢得 $SAND 奖励&#xff01; 无论你是专业的设计师&#xff0c;还是仅仅喜欢创造美丽的艺术&#xff0c;这场…

有趣的阻抗变换

阻抗变换在很多人看来很神秘&#xff0c;甚至不可理喻&#xff1a; “什么是匹配网络&#xff1f;” “为什么要在负载电路之前加这么多电感电容&#xff1f;” “如果负载是100欧姆要与源阻抗50欧匹配&#xff0c;直接在负载并联一个100欧负载不就行了吗”……这样的问题常…

项目管理软件中日历的作用

为什么在项目管理软件中使用日历&#xff1f;日历是跟踪即将举行的会议、截止日期和里程碑的有用工具。它们可以帮助您可视化您的日程安排并提醒您重要事件&#xff0c;例如假期和休假时间。 虽然人们经常有各种各样的日历工具可供选择&#xff0c;包括从办公室墙上的纸质日历…

Stochastic Approximation 随机近似方法的详解之(二)Robbins-Monro Algorithm

6.2 Robbins-Monro Algorithm RM算法是随机近似领域的先驱性工作。众所周知的随机梯度下降算法是RM算法的一种特殊情况。后面我们再介绍具体的细节。 先看一个例子&#xff1a; 我们想要去求下面这个等式的根&#xff0c; BTW&#xff0c;很多问题可以被转化为求根问题。比…

嵌入式学习笔记——基于Cortex-M的单片机介绍

基于Cortex-M的单片机介绍前言生产厂商及其产品线ARM单片机的产品线命名规则留个作业习单片机的资料准备STM32开发所需手册1.芯片的数据手册作业2前言 本文继续接着上一篇中关于Cortex-M的介绍&#xff0c;来记录一些关于ARM系单片机的知识。 生产厂商及其产品线 芯片厂商在…

论坛性能测试难点有哪些?

1 测试工具方面 用户和业务模型分析搭建合适的脚本开发&#xff08;不根据用户和业务的模型来开发脚本&#xff0c;认为要回归成功即可&#xff09;合适的需求分析转化为场景设计&#xff08;不知道如何根据需求进行场景设计&#xff09;大容量系统的数据生成和使用大型系统的…

金蝶国产化中间件和人大金仓数据库

金蝶Apusic分布式消息队列不需要配置用户名密码rabbitmq:enable: truehost: 192.168.1.233port: 5672<!-- Spring Boot RabbitMQ 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</ar…

webrtc音频系列——4、RTP与RTCP协议

如果让你从0开发一套实时互动直播系统&#xff0c;你首先要选择网络传输协议。UDP 还是 TCP&#xff1f;答案是&#xff1a;UDP。为什么实时传输不能用 TCP &#xff1f;TCP 的目的就是实现数据的可靠传输&#xff0c;因此他有一套 握手&#xff0c;发送 -> 确认&#xff0c…

linux下安装jenkins

1.初始化Jenkins安装环境 系统版本&#xff1a;Red Hat Enterprise Linux 8.7 将脚本文件jenkins_install_env.sh 、 jenkins_install.sh和apache-maven-3.6.2-bin.tar.gz、jdk-8u251-linux-x64.tar.gz都上传到/usr/local/src目录下执行jenkins_install_env.sh脚本初始化Jenki…

嵌入式开发工具箱【持续更新中】【VMware、Ubuntutftp、nfs、SecureCRT、XShell、Source Insight 4.0】

一、概述 本文主要介绍嵌入式开发过程中需要用到的工具及简单的使用方法。避免在搭建嵌入式开发环境时&#xff0c;需要四处寻找文档&#xff0c;收藏此文章&#xff0c;一文搞定。 大多数嵌入式开发环境是使用Linux作为目标开发系统&#xff0c;所以开发主机一般都是Linux系统…

若依学习(前后端分离版)——启动时发生了啥?(@PostConstruct)(mybatis log free)

我们可以发现若依启动时执行了一些sql我们可以安装一个插件mybatis log free 来更好的进行sql查看 &#xff0c;安装后需要修改一下若依的日志配置如下查看日志&#xff0c;我们发现执行了三个方法&#xff08;&#xff09;&#xff0c;分别查询了一些数据。以第二个方法为例子…

python 如何存储数据 (python 的文件和异常)

文章目录存储数据1. 使用 json.dump() 和 json.load()json.dump()2. 保存和读取用户生成的数据存储数据 很多程序都要求用户输入某种信息&#xff0c;如让用户存储游戏首选项或提供要可视化的数据。不管专注的是什么&#xff0c;程序都把用户提供的信息存储在列表和字典等数据结…

这些个 axios 工具函数,你都掌握了吗

前言 周末过得真快&#xff0c;看个源码时间就过去了&#x1f440;。 在上周看做项目的时候看到了项目里封装的 axios&#xff0c;对其封装的原理没有弄清楚&#xff0c;于是周末的时候便抽了点空闲时间来看了看 axios 的源码&#xff0c;将其研究研究。 源码阅读 这里就不…

实战:一天开发一款内置游戏直播的国产版Discord应用【附源码】

游戏直播是Discord产品的核心功能之一&#xff0c;本教程教大家如何1天内开发一款内置游戏直播的国产版Discord应用&#xff0c;用户不仅可以通过IM聊天&#xff0c;也可以进行语聊&#xff0c;看游戏直播&#xff0c;甚至自己进行游戏直播&#xff0c;无任何实时音视频底层技术…

数据增广真有那么神奇吗?

作者&#xff1a;皮皮雷 来源&#xff1a;投稿 编辑&#xff1a;学姐 论文题目 How Effective is Task-Agnostic Data Augmentation for Pretrained Transformers? 论文作者 S. Longpre, Y. Wang, and C. DuBois 论文发表于 2020 EMNLP findings 摘要 任务无关的数据增广…

chatgpt功能展示

Chatgpt 不知道大家刷抖音的时候是否刷到了人工智能要取代人类的一些短视频&#xff0c;他们所提到的主角就是一个AGI模型——chatgpt&#xff0c;资本对其的追求程度可以用火爆&#x1f525;来形容了吧&#xff0c;先给大家讲一下chatgpt吧&#xff0c;如果没兴趣看我扯犊子可…

网络安全入门学习:社会工程学

在电影《我是谁&#xff1a;没有绝对安全的系统》中&#xff0c;主角本杰明充分利用自己高超的黑客技术&#xff0c;非法入侵国际安全系统&#xff0c;并在最后逃之夭夭。在电影中&#xff0c;有一句经典的台词&#xff1a; 所有黑客手段中最有效的、最伟大的幻想艺术——社会…

windows10安装ubantu双系统

windows10安装ubantu双系统 文章目录windows10安装ubantu双系统一、安装前准备1.前期说明2.制作U盘启动器3.设置硬盘分区相关4.设置给ubantu系统的硬盘大小&#xff0c;设置为未分配&#xff08;删除卷&#xff09;二、进行安装1.设置bios相关2.进入bios启动界面选择U盘安装3.进…

快速入门 Python 数据分析实用指南

Python 现如今已成为数据分析和数据科学使用上的标准语言和标准平台之一。那么作为一个新手小白&#xff0c;该如何快速入门 Python 数据分析呢&#xff1f; 下面根据数据分析的一般工作流程&#xff0c;梳理了相关知识技能以及学习指南。 数据分析一般工作流程如下&#xff…