WebRTC实战 | 视频云

news2024/12/24 2:37:22

前言

WebRTC是当前实时通信领域的重要技术之一,具有广泛的应用前景。可以实现音频、视频和数据的实时传输。支持点对点通信、多方会议、屏幕共享等多种应用场景,同时具有高质量、低延迟、强安全性等特点,是开发实时通信应用的理想选择。可以应用于远程协作、在线教育、在线医疗、物联网等领域,具有广泛的商业应用前景。WebRTC技术包括了音视频的采集、编解码、网络传输、显示等功能,本文主要从API使用说明和注意细节方面介绍一下WebRTC的大致情况。

根据W3C的WebRTC1.0:Real-time Communication Between Browsers规范,WebRTC的源码中定义了两套主要的C++接口,分别是MediaStream与PeerConnection相关的API,MediaStream 相关API定义在源码api\media_stream_interface.h中。主要涉及这4个概念:source、sink、meidatrack、mediastream。

MediaStream API

MediaAPI中有两个重要组成:MediaStreamTrack、MediaStream。MediaStreamTrack对象代表单一类型的媒体流,产生自客户端的media source,可以是音频或者视频,但只能是其中一种,是音频称作audio track,视频的话称作video track,这其实就是我们平时所说的音轨与视频轨。

一个track由source与sink组成。source给track提供数据。

MeidiaStream用于将多个MediaStreamTrack对象打包到一起。一个MediaStream可包含audio track 与video track。类似我们平时的多媒体文件,可包含音频与视频。

一个MediaStream对象包含0或多个MediaStreamTrack对象。MediaStream中的所有MediaStreamTrack对象在渲染时必须同步。就像我们平时播放媒体文件时,音视频的同步。

简单点说,source 与sink构成一个track,多个track构成MediaStram。

source 与 sink

在MediaTrack的源码中,MediaTrack都是由对应的source和sink组成的。

浏览器中存在从source到sink的媒体管道,其中source负责生产媒体资源,包括多媒体文件,web资源等静态资源以及麦克风采集的音频,摄像头采集的视频等动态资源。而sink则负责消费source生产媒体资源,也就是通过,video等媒体标签进行展示,或者是通过RTCPeerConnection将source通过网络传递到远端。RTCPeerConnection可同时扮演source与sink的角色,作为sink,可以将获取的source降低码率,缩放,调整帧率等,然后传递到远端,作为source,将获取的远端码流传递到本地渲染。

检测获取音视频设备

使用MediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。可以用来取得任何硬件资源的媒体数据。提供访问链接媒体输入的设备,如摄像头、麦克风、屏幕共享等。它可以使你取得任何硬件资源的媒体数据。

通过MediaDevices的方法 enumerateDevices() 请求一个可用的媒体输入和输出设备的列表,例如麦克风,摄像机,耳机设备等。返回的 Promise 完成时,会带有一个描述设备的 MediaDeviceInfo的数组。

75cdc488d4763d84e488d51533fca9e1.png

采集本地音视频数据

MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。

它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。

eaf1a15f05aa76a6ecd9508ad132e43f.png 

视频约束

getUserMedia()函数接收一个参数MediaStreamConstraints,MediaStreamConstraints对象用于指定要请求的轨道类型(音频,视频或二者)以及(可选)每个轨道的任何要求。

约束项可以具有下面这两个属性中的一个或两个:

  • video—表示是否需要视频轨道audio—表示是否需要音频轨道

  • 如果仅指定是否包含音频和视频流的时候,可以这样 

851cccf16cad9a1b9a6736176422c819.png

设置分辨率

可以用video中的width和height属性从网络摄像头请求一定的分辨率,比如请求1280×720分辨率的视频流。直接设置的width和height会被视为“ideal”(理想)值,浏览器会尽可能的保持这个分辨率,但是也有可能会返回一个接近的分辨率,因为我们设置的分辨率可能摄像头不支持

212776c85ea27a038b12b1e76b126a41.png

可以用min,max和exact关键字来限制分辨率范围,从而得到最佳的分辨率

4aad45e66868004d280857126de40dc7.png

可以使用deviceId指定被用于捕捉流的设备ID。这个设备ID是唯一的,并且在同一个来源的会话中是相同的。需要首先使用MediaDevices.enumerateDevices()来获取设备id。以下是一些常用的约束条件:

3f09373923a2a52f4310b757abde5a01.png

MediaDevices.getSupportedConstraints()的支持。这个函数会返回一个字典,列出用户代理支持的约束:

366e953463f403d1da50f4f0c3546823.png

设置码率

在 通 话 过 程 中 实 时 更 改 视 频 码 率 , 主 要 涉 及 对RTCRtpEncodingPara-meters.maxBitrate 的修改,maxBitrate 能够接受的码率单位是 bps。

bafcbc85f0a9c0e94bd7e4e9275494f7.png

兼容性问题

有一部分老的浏览器不能兼容navigator.mediaDevices.getUserMedia来获取麦克风和摄像头,可用如下来获取

670b2a40c2cf0151eed4018a62cef47c.png

Safari浏览器 不支持多个 tab getUserMedia,否则前一个 tab 会停止采集,远端流也有可能出现黑屏无声。

屏幕共享

MediaDevices 接口的 getDisplayMedia() 方法提示用户去选择和授权捕获展示的内容或部分内容(如一个窗口)在一个MediaStream里。用法和getUserMedia类似。

bff00c6868e51635f4e3ae43787890d1.png

Safari默认只能共享整个屏幕,不支持选择应用和浏览器标签页。

设备监听

为了在应用程序中监测媒体设备的变化,WebRTC提供了devicechange事件和ondevicec-hange事件句柄,与navigator.mediaDevices结合即可实时监控媒体设备的热插拔。

52782fd06c2e100ed196ed1c828bd768.png

视频质量调整策略

webrtc 提供了三种策略:

  • MAINTAIN_FRAMERATE:保帧率,降分辨率,该模式的使用场景为视频模式。

  • MAINTAIN_RESOLUTION: 保分辨率降帧率,使用场景为屏幕共享或者文档模式,对清晰度要求较高的场景。

  • BALANCED: 平衡帧率与分辨率。默认关闭,需要通过 WebRTC-Video-BalancedDegradation 开启。

    a5ad74bab83e5d96e91955f36ceeda39.png

webrtc API层提供了自适应策略的设置接口,通过设置 MediaStreamTrack 的 contentHint 属性就可以了。在WebRtcVideoSendStream::GetDegradationPreference 函数中会将 ContentHint 转换成 DegradationPreference。

Audio Content Hints

  • "speech":指定音频源为讲演,可以适当使用噪声消除或者提升源的可理解性等

  • "speech-recognition":指定音频源为语音识别,可以适合提高输入信号的清晰度以进行转录并关闭用于人类消费的音频处理组件

  • "music":指定音频源为音乐,可能意味着调整或关闭用于处理语音数据的音频处理组件,以防止音频失真

Video Content Hints

  • "motion":指定为运动的时候,降低分辨率以保持帧率

  • "detail":指定为细节的时候,降低帧率以保持分辨率,屏幕分享一般默认为细节模式

  • "text":指定为文本,降低帧率以保持分辨率,当编码器的文本模式可用的时候,使用文本模式。此设置通常会针对生成的单个帧中的细节进行优化,而不是平滑播放,并且可能会利用针对文本渲染进行优化的编码器工具,对于属性值为“text”的视频轨道,如果编码编解码器为AV1,则激活“text”模式的编码工具。 

85f3f00d25faacb26f78731213ca6032.png

RTCPeerConnection API

RTCPeerConnection接口代表一个由本地计算机到远端的WebRTC连接。该接口提供了创建,保持,监控,关闭连接的方法的实现。
其接口的定义如下:

86685fe6aae2b7086424a5f783bcbdf2.png

其中有一个可选参数RTCConfiguration, 在文档中定义如下;

0f45fb00a0deafd430d4d7c1f209543f.png

iceServers,由多个RTCIceServer组成需要填入stun或turn服务的地址;

iceTransportPolicy :ice的传输策略,默认值是all允许考虑所有候选者,值有"all",“public” 已弃用 ,“relay” 只收集中继候选者;

rtcpMuxPolicy:收集 ICE 候选时是否使用的 RTCP 多路复用策略。值有 'negotiate’和 ‘require’;

bundlePolicy:‘balanced’、‘max-compat’和’max-bundle’;默认是balanced。

各个含义如下:

  • Balanced实际就是音频轨、视频轨各自各自使用一个传输通道,是分开的。其中多路音频轨是共用同一个传输通道、多路视频轨也是使用同一个通道。

  • max-compat是最大兼容性,怎样才能达到最大的兼容性呢?就是每一个轨都有自己的通道,如果我有这个两个音频,一个视频,就有三个通道,就是每个音频走自己的,那视频也是一样的。等到Balanced策略不成功的时候,就使用max-compat这种方式。

  • max-bundle就是最大化的使用一个绑定,那就是将所有的这些这个媒体的这个流都用一个这个通道进行传输。这是webrtc建议的方式,这样的话对于底层来说就比较简单了,而且你建立这个连接之后,只需要一个证书,而不需要一堆证书,否则的话,你每一个连接都需要一个证书,就会非常的耗费时间。

一般使用方式如下:

725b2bb1cb27e5c8ff2b54e3494e3cad.png

主要方法:

  • addIceCandidate 向ICE代理提供远程候选人。

  • addStream 添加MediaStream作为视频或音频的本地源。

  • addTrack 添加MediaStreamTrack

  • close 关闭连接。

  • createAnswer 创建answer。此方法的两个第一个参数是成功回调和错误回调。可选的第三个参数是要创建的选项。

  • createDataChannel 创建一个新的数据通道RTCDataChannel

  • createOffer 用来创建offer,创建成功后调用setLocalDescription方法将localDescription设置为offer,localDescription即为我们需要发送给应答方的sdp

  • getConfiguration 获取配置信息

  • getStats 创建一个新的RTCStatsReport,其中包含有关连接的统计信息。

  • removeStream 删除MediaStream作为视频或音频的本地源。

  • removeTrack 删除MediaStreamTrack作为视频或音频的本地源。

  • setLocalDescription 设置本地连接描述信息。该方法采用三个参数,RTCSessionDescription对象,成功回调,失败回调。

  • setRemoteDescription 设置远程连接描述信息

主要事件:

  • onaddstream 事件用来监听通道中新加入的流,当addstream事件被触发时,会调用此处理程序。当远程方将MediaStream添加到此连接时,会发送此事件。

  • ondatachannel 当数据通道事件被触发时,会调用此处理程序。将RTCDataChannel添加到此连接时发送此事件。

  • onicecandidate 当RTCIceCcandidate对象添加时,会发送此事件。

  • oniceconnectionstatechange 当iceConnectionState的值发生更改时,会发送此事件。

  • onnegotiationneeded 当触发需要协商的事件时,会调用此处理程序。此事件由浏览器发送,以通知将来某个时候需要进行协商。

  • onremovestream 当信号状态更改事件被触发时,会调用此处理程序。当signalingState的值发生变化时,会发送此事件。

  • onsignalingstatechange当removestream事件被激发时,会调用此处理程序。此事件是在从该连接中删除MediaStream时发送的。

  • ontrack当远程方将MediaStream添加到此连接时,会发送此事件。

    RTCPeerConnection使用步骤如下:

1、创建一个新的 RTCPeerConnection对象,将采集到的音视频轨道,通过addTrack进行添加,发送给远端。远端可以通过监听ontrack来监听音视频的到达,并进行播放。

f5aed8aab9c1a50c13f3163385dc72e3.png                   

2、交换 SDP,交换 SDP 的目的是为了让对方知道彼此具有哪些能力,然后根据双方各自的能力进行协商,协商出大家认可的音视频编解码器、编解码器相关的参数(如音频通道数,采样率等)、传输协议等信息。创建 offer 设置为 pc1的本地描述,通过信令服务器发送到远端,作为 pc2的远端描述.pc2收到后创建answer设置成自己的本地描述,

56c90b9b6bd0962cbe5fe1fd15c2e965.png

3、收集Candidate,应答方收到发起方发送的ICE数据时,调用pc的addIceCandidate方法。pc2.addIceCandidate(new RTCIceCandidate(ice))复制代码发起方收到应答方发送的ICE数据时,同样调用RTCPeerConnection对象的addIceCandidate方法。

047c64a407576850a178a38882822511.png

至此,一个最简单的WebRTC连接就建立完成了。

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

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

相关文章

从“嘿,Siri”到元宇宙,苹果还有多远距离要走?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 在当前的科技浪潮中,元宇宙的概念凭借其无限的想象力和可能性,像一颗耀眼的新星吸引着世界的目光。巨大的发展潜力,吸引着一波又一波的企业,前赴后继地向元宇宙发起冲锋。 在这…

27.打包项目

目录 1 打包成dist 2 flask配合dist 3 以文件形式打开 1 打包成dist 项目路径下输入 npm run build 在项目路径下会出现一个dist 打包后直接双击打开index.html是没有用的 因为你双击打开是file协议,你需要一个http协议 2 flask配合dist 我们可以搞一个fla…

「企业信息架构」EA874:信息架构治理概述

信息治理是一个程序,它实现决策权和支持机制,以确保整个企业信息的准确性、完整性、一致性、可访问性和安全性。为了维持信息治理,需要在业务(而不是IT)中确定和建立几个角色。这三个角色可能单独存在,也可…

分布式光伏消纳的微电网群共享储能配置策略研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

【AUTOSAR】Bootloader说明(四)---- 升级主函数

刷新主函数uds_refresh_main() 当执行完初始化后,DSP进入刷新主函数。 主函数是一个无穷循环函数,完成诊断消息的接收、处理,诊断状态的刷新等。 函数原型 void bblk_normal_isr(void) 函数作用 完成看门狗服务,清楚定时器中…

如何在ImageSpan上面绘制文本?

简介:TextOnImageSpan 前阵子碰到一个需求:在文本中内嵌图标,并在图标上面绘制特定文本。很自然就会想到用SpannableString去实现,但经过一系列的研究捣鼓,发现根本就没有能在图标上绘制文本的span类,于是乎…

单马达可换档六足机器人前进功能的实现

1. 运动功能说明 本文示例将实现R046样机单马达可换档六足机器人前进的功能。 2. 结构说明 本样机只有一个圆周舵机,却可以通过换挡机构实现前进和转向两种行走姿态。 样机由一个圆周舵机带动一个等速齿轮组(下图所示两枚蓝色齿轮)&#xff0…

C#,码海拾贝(26)——求解“一般带状线性方程组”之C#源代码

在大型稀疏方程组中,最常见的是带状方程组,其系数矩阵是带状矩阵,非零元素仅集中在对角线附近的带状区域内。 特别的,当上下带宽相等时我们A称方程组为等带宽方程组。总带宽为3的等带宽方程组我们又叫三对角方程组。 using Syste…

如何在 Elasticsearch 论坛/社群上提出高质量的技术问题?

在网络的海洋中寻求帮助,有时可能会让你感到茫然。你可能已经准备好详细描述你的问题,但如果你不知道如何有效地提问,你可能会发现自己在等待回答时感到挫败。 这篇文章的目标是为你提供一些提示,让你更快地获取你在论坛上的技术问…

数据库管理-第八十二期 EMCC升级教程(20230606)

数据库管理 2023-06-06 第八十二期 EMCC升级教程1 升级EMCC1.1 升级概览1.2 拷贝相关文件1.3 升级OPatch1.4 升级OMSPatcher1.5 升级WLS1.6 升级OMS 2 升级Agent2.1 升级概览2.2 拷贝相关文件2.3 安装或升级AgentPatcher2.4 升级agent 3 升级Oracle数据库ASH包总结 第八十二期 …

2. 分布式文件系统 HDFS

2. 分布式文件系统 HDFS 1. 引入HDFS【面试点】 问题一:如果一个文件中有 10 个数值,一行一个,并且都可以用 int 来度量。现在求 10 个数值的和 思路: 逐行读取文件的内容把读取到的内容转换成 int 类型把转换后的数据进行相加…

一文打通基于注解管理Bean

目录 开启组件扫描 情况一:最基本的扫描方式 情况二:指定要排除的组件 情况三:仅扫描指定组件 使用注解定义 Bean Autowired注入 ①场景一:属性注入 ②场景二:set注入 ③场景三:构造方法注入 ④…

Hbase安装指南

Hbase简介 HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实现,类似Google Bigtable利用GFS作为其文件存储系统,HBase利用Had…

Java基础学习+面向对象(一)

一,基础概念介绍 1.1Java跨平台原理(一次编译,处处运行) Java 源代码经过编译,生成字节码文件,交由 Java 虚拟机来执行,不同得系统有不同得JVM,借助JVM 实现跨平台。就比如说我们在 Windows 下…

基于Java+uniapp微信小程序的购物商城系统设计与实现

博主介绍:擅长Java、微信小程序、Python、Android等,专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟 Java项目精品实战案例…

linux和windows爬虫有什么区别

Linux和Windows作为操作系统对于爬虫的差异不是特别大,因为两个操作系统同时都可以用于编写运行爬虫的程序。 主要的差异可能源于开发工具和环境的差异。Linux上通常使用命令行工具来编写和运行爬虫程序,而Windows则更加倾向于使用图形化界面的编程软件…

chatgpt赋能python:Python定义父类的意义及用法

Python定义父类的意义及用法 Python是一种高级编程语言,具有强大的面向对象编程(OOP)能力。在OOP的设计中,定义一个父类可以让多个子类继承其属性和方法,从而提高代码重用率并简化程序的开发。 如何定义Python中的父…

一起看 I/O | 借助 Google Play 管理中心价格实验,优化定价策略

作者 / Google Play 产品经理 Phalene Gowling 今年 Google I/O 大会上的 "通过 Google Play Commerce 提升收益" 演讲重点为您介绍了深度集成至 Google Play 的最新创收工具。此工具专注于帮您优化定价策略。为您的产品或内容确定合适的价格是实现更出色的用户生命周…

大会议题重磅出炉,豪华阵容等你面基!RustChinaConf 2023!【附第一天议程】

本次大会议题品质一流,嘉宾多来自行业一线,干货多多,且在各领域遍地开花,可看出Rust星星之火在中国已成燎原之势! 大会时间地址 6.17 - 6.18 浦东新区张杨路777号 上海锦江汤臣洲际酒店 官网地址 https://rustcc.cn/20…

华为云发布面向消费终端的企业云原生白皮书,开辟移动时代的云原生路径

2013年,程序员Matt Stine提出“CloudNative”概念,后来他又将这项技术的特点归纳为模块化、可观察、可部署、可测试、可替换、可处理6项,这就是大名鼎鼎的云原生。 十年过去,云原生的价值在科技界可谓无人不知,谁都能说…