当前位置: 首页 > news >正文

WebRTC | 实现数据流的一对一通信

目录

一、浏览器对WebRTC的支持

二、MediaStream与MediaStreamTrack

三、RTCPeerConnection

1. RTCPeerConnection与本地音视频数据绑定

2. 媒体协商SDP

3. ICE

(1)Candidate信息

(2)WebRTC收集Candidate

(3)交换Candidate

4. SDP与Candidate消息的交换

五、远端音视频渲染


        在浏览器上实现一对一实时音视频通信是WebRTC最主要的应用场景。由于主流的浏览器都已支持了WebRTC,因此在浏览器中实现一对一通信很容易,只要几行代码就可以实现。

一、浏览器对WebRTC的支持

        目前像Chrome、Safari、Firefox等世界上主流的浏览器都已支持WebRTC。不过需要注意的是,微软的IE浏览器明确表示不支持WebRTC,而是在新推出的Edge浏览器上支持它。之所以不在IE浏览器上支持WebRTC,主要有两方面的原因:一是IE浏览器将会逐渐被Edge所替代;二是支持WebRTC要对浏览器架构做大规模调整,成本太高。

支持WebRTC的浏览器

二、MediaStream与MediaStreamTrack

        在WebRTC中有两个重要的概念,即MediaStream和MediaStreamTrack。

        MediaStreamTrack称为“轨”,表示单一类型的媒体源,比如从摄像头采集到的视频数据就是一个MediaStreamTrack,而从麦克风采集的音频又是另外一个MediaStreamTrack。

        MediaStream称为“流”,它可以包括0个或多个MediaStreamTrack。

        MediaStream有两个重要作用,一是可以作为录制或者渲染的源,这样我们就可以将Stream中的内容录制成文件或者将Stream中的数据通过浏览器中的<video>标签播放出来;二是在同一个MediaStream中的MediaStreamTrack数据会进行同步(比如同一个MediaStream中的音频轨和视频轨会进行时间同步),而不同MediaStream中的MediaStreamTrack之间不进行时间同步。

三、RTCPeerConnection

        RTCPeerConnection对象是WebRTC的核心,它是WebRTC暴露给用户的统一接口,其内部由多个模块组成,如网络处理模块、服务质量模块、音视频引擎模块等等。可以把它想象成一个超级socket,通过它可以轻松地完成端到端数据的传输。更让人惊讶的是,它还可以根据实际网络情况动态调整出最佳的服务质量。

1. RTCPeerConnection与本地音视频数据绑定

        对于绑定数据的问题,RTCPeerConnection对象为我们提供了两种方法:一个是addTrack();另一个是addStream()。这两种方法都可以实现将采集到的数据与RTCPeerCon nection绑定的作用,不过由于WebRTC规范中已经将addStream()标记为过时,因此建议尽量使用addTrack()方法,以免以后出现兼容性问题。

        当客户端从服务端接收到joined消息后,它会创建RTCPeer Connection对象,然后调用addTrack()函数将其与之前通过getUserMedia()接口采集到的音视频数据绑定到一起。

2. 媒体协商SDP

        当RTCPeerConnection对象与音视频绑定后,紧接着需要进行媒体协商。比如你默认使用的编码器是VP8,要想与对方通信,还需要知道对方是否可以解码VP8的数据。如果对方不支持VP8解码,那你就不能使用这个编码器。再比如,通信中的一方说,我的数据是使用DTLS-SRTP加密的,而另一方也必须具备这种能力,否则双方无法通信。这就是媒体协商。

        进行媒体协商时,交换的内容是SDP格式的。

         协商的发起方是用户A,当它创建好RTCPeerConnection对象并与采集到的数据绑定后,开始执行图中的第❶步,即调用RTCPeerConnection对象的createOffer接口生成SDP格式的本地协商信息Offer;本地协商信息Offer生成后,再调用setLocalDescription接口,将Offer保存起来(第❷步);之后通过客户端的信令系统将Offer信息发送给远端用户B(第❸步)。此时用户A的媒体协商过程暂告一段落(还未完成)。

        用户B通过信令系统收到用户A的Offer信息后,调用本地RTCPeerConnection对象的setRemoteDescription接口,将Offer信息保存起来(第❹步);这一步完成后,再调用createAnswer接口创建Answer消息(第❺步)(Answer消息也是SDP格式,里边记录的是用户B端的协商信息);Answer消息创建好后,用户B调用setLocalDescription接口将Answer信息保存起来(第❻步)。至此,用户B端的媒体协商已经完成。接下来,用户B需要将Answer消息发送给A端(第❼步),以便让用户A继续完成自己的媒体协商。

        用户A收到用户B的Answer消息后,就可以重启其未完成的媒体协商了。用户A需要调用RTCPeerConnection对象的setRemoteDescription接口将收到的Answer消息保存起来(第❽步)。执行完这一步后,整个媒体协商过程才算最终完成。

3. ICE

        当媒体协商完成后,WebRTC就开始建立网络连接了,其过程称为ICE(Interactive Connectivity Establishment,交互式连接建立)。

        更确切地说,ICE是在各端调用setLocalDescription()接口后就开始了。其操作过程为:收集Candidate(Candidate,可连接的候选者。每个候选者是包含IP地址和端口等内容的信息集。),交换Candidate,按优先级尝试连接。       

(1)Candidate信息

         Candidate正是WebRTC用来描述它可以连接的远端的基本信息,因此它是至少包括{address,port,protocol}三元组的一个信息集。

ICE收集Candidate,包含:传输方式(UDP、TCP、TLS和TURN)、连接策略/类型(host、srflx、prflx、relay)、IP、端口号等。

        WebRTC将Candidate分成了四种类型,即host、srflx、prflx及relay,且它们还有优先级次序,其中host优先级最高,relay优先级最低。比如WebRTC收集到了两个Candidate,一个是host类型,另一个是srflx类型,那么WebRTC一定会先尝试与host类型的Candidate建立连接,如果不成功,才会使用srflx类型的Candidate。

* host(主机):host地址是设备的本地地址,也称为私有地址。它是设备直接连接到网络的地址,没有经过NAT转换。在ICE中,host地址用于直接建立点对点连接。
* srflx(服务器反向映射):srflx地址是通过STUN服务器获取的。STUN服务器可以帮助设备发现自己在NAT后面的公共IP地址和端口。srflx地址允许设备在NAT环境中建立直接的点对点连接。
* prflx(对等反向映射):prflx地址是通过TURN服务器获取的。当设备无法直接建立连接时,它可以通过STUN服务器进行中继。STUN服务器会分配一个临时的公共IP地址和端口给设备,以便进行通信。
* relay(中继):relay地址是通过TURN服务器获取的,用于设备之间的中继通信。当设备无法直接建立连接时,它们可以通过TURN服务器进行通信,所有的数据都经过服务器转发。

WebRTC通信时会按照内网、P2P、relay这样的次序尝试连接(见后文ICE详解):
1. 内网连接对应host连接策略。host连接表示直接在本地设备上建立的连接,也就是在同一局域网内的设备之间的直接连接。
2. P2P连接对应srflx和prflx连接策略。srflx(server reflexive)和prflx(peer reflexive)连接都是通过STUN服务器获取的公共IP地址,用于建立点对点连接。srflx连接是通过NAT后的公共IP地址建立的连接,而prflx连接是对等方自己的NAT映射地址。
3. 中继连接对应relay连接策略。当无法建立直接的P2P连接时,WebRTC会使用TURN服务器作为中继,建立relay连接。relay连接通过中继服务器传递数据,确保数据的可靠传输。 

(2)WebRTC收集Candidate

        WebRTC收集Candidate时有几种途径:host类型的Candidate,是根据主机的网卡个数来决定的,一般来说,一个网卡对应一个IP地址,给每个IP地址随机分配一个端口从而生成一个host类型的Candidate;srflx类型的Candidate,是从STUN服务器获得的IP地址和端口生成的;relay类型的Candidate,是通过TRUN服务器获得的IP地址和端口号生成的。

(3)交换Candidate

        WebRTC收集好Candidate后,会通过信令系统将它们发送给对端。对端接收到这些Candidate后,会与本地的Candidate形成CandidatePair(即连接候选者对)。有了CandidatePair,WebRTC就可以开始尝试建立连接了。

        Candidate的交换不是等所有Candidate收集好后才进行的,而是边收集边交换。

4. SDP与Candidate消息的交换

        当通信双方需要交换信息SDP与Candidate消息时就用到了message信令。发起方首先向信令服务器发送message消息,服务端收到message消息后不做任何处理,直接将该消息转发给目标用户。

        消息交换分成三个步骤,即发起方发送要交换的消息,服务端收到消息后进行转发,客户端接收消息。

五、远端音视频渲染

        WebRTC给我们提供了一个非常好的接口,即RTCPeerConnection对象的ontrack()事件。每当有远端的音视频数据传过来时,ontrack()事件就会被触发。因此只需要给ontrack()事件设置一个回调函数,就可以拿到远端的MediaStream了。

相关文章:

WebRTC | 实现数据流的一对一通信

目录 一、浏览器对WebRTC的支持 二、MediaStream与MediaStreamTrack 三、RTCPeerConnection 1. RTCPeerConnection与本地音视频数据绑定 2. 媒体协商SDP 3. ICE &#xff08;1&#xff09;Candidate信息 &#xff08;2&#xff09;WebRTC收集Candidate &#xff08;3&…...

基于MATLAB小波变换的信号突变点检测

之前在不经意间也有接触过求突变点的问题。在我看来&#xff0c;与其说是求突变点&#xff0c;不如说是我们常常玩的"找不同"。给你两幅图像&#xff0c;让你找出两个图像中不同的地方&#xff0c;我认为这其实也是找突变点在生活中的应用之一吧。回到找突变点位置上…...

JUC并发编程(JUC核心类、TimeUnit类、原子操作类、CASAQS)附带相关面试题

目录 1.JUC并发编程的核心类 2.TimeUnit&#xff08;时间单元&#xff09; 3.原子操作类 4.CAS 、AQS机制 1.JUC并发编程的核心类 虽然java中的多线程有效的提升了程序的效率&#xff0c;但是也引发了一系列可能发生的问题&#xff0c;比如死锁&#xff0c;公平性、资源管理…...

个人用C#编写的壁纸管理器 - 开源研究系列文章

今天介绍一下笔者自己用C#开发的一个小工具软件&#xff1a;壁纸管理器。 开发这个小工具的初衷是因为Windows操作系统提供的功能个人不满意&#xff0c;而且现在闲着&#xff0c;所以就随意写了个代码。如果对读者有借鉴参考作用就更好了&#xff0c;能够直接代码段复用即可。…...

iTextSharp 生成PDF

示例代码定义了一个名为PdfController的API控制器&#xff0c;其中的GeneratePdf方法创建了一个新的PDF文档&#xff0c;并将内容添加到文档中。最后&#xff0c;将文档内容转换为字节数组&#xff0c;并通过File方法返回给前端。 注意&#xff0c;你需要在你的项目中添加对iT…...

基于微信小程序的传染病酒店隔离平台设计与实现(Java+spring boot+MySQL+微信小程序)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于微信小程序的传染病酒店隔离平台设计与实现&#xff08;Javaspring bootMySQL微信小程序&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;…...

vue3中用watch监听响应式数据的注意点

如果你在vue3中使用reactive()方法创建响应式数据&#xff0c;然后又用torefs()方法将响应式数据解构成单一的ref响应式数据。 此时&#xff0c;如果你想用watch监听解构出来单一的响应式数据&#xff0c;watch不起作用。 此时&#xff0c;你需要用watch监听之前的reactive()…...

Jmeter(五) - 从入门到精通 - 创建网络计划实战和创建高级Web测试计划(详解教程)

1.简介 上一篇中已经将其的理论知识介绍了一下&#xff0c;这一篇就带着大家一步一步的把上一篇介绍的理论知识实践一下&#xff0c;然后再说一下如何创建高级web测试计划。 2.网络计划实战 通过上一篇的学习&#xff0c;将其分类为&#xff1a; &#xff08;1&#xff09;不需…...

【单片机】51单片机,TLC2543,驱动程序,读取adc

TLC2543 是一款 12 位精密模数转换器 (ADC)。 1~9、11、12——AIN0&#xff5e;AIN10为模拟输入端&#xff1b; 15——CS 为片选端&#xff1b; 17——DIN 为串行数据输入端&#xff1b;&#xff08;控制字输入端&#xff0c;用于选择转换及输出数据格式&#xff09; 16——…...

誉天HCIE-Cloud_Computing3.0课程简介

课时&#xff1a;60 第一天 1. 华为云 Stack 解决方案及架构介绍 3. 华为云 Stack 的安装流程解析及规划设计 4. 华为云 Stack 的网络平面的规划解析 5. 华为云 Stack Deploy 部署工具的安装&#xff0c;配置&#xff0c;创建工程&#xff0c;下载 LLD 表 6. 华为云 Stack 的 …...

Unity之ShaderGraph 节点介绍 Procedural节点

程序化 噪声Gradient Noise&#xff08;渐变或柏林噪声&#xff09;Simple Noise&#xff08;简单噪声&#xff09;Voronoi&#xff08;Voronoi 噪声&#xff09; 形状Ellipse&#xff08;椭圆形&#xff09;Polygon&#xff08;正多边形&#xff09;Rectangle&#xff08;矩形…...

期权定价模型系列【1】—BSM通用式模型

这是期权定价模型专栏的第一篇文章&#xff0c;此专栏旨在分享一些期权定价模型&#xff0c;将会从最基础的BSM模型开始写起&#xff0c;逐步扩散到蒙特卡洛模拟、二叉树等数值法模型&#xff0c;以及跳跃扩散模型、随机波动率模型&#xff0c;神经网络模型等等。 如果你觉得有…...

HA3 SQL样本实验:一种混合计算查询的全新样本解决方案

作者&#xff1a;陆唯一(芜霜) HA3&#xff08;对外开源代号&#xff1a;Havenask &#xff09;是阿里智能引擎团队自研的大规模分布式检索系统&#xff0c;广泛应用于阿里内部的搜索业务&#xff0c;是十多年来阿里在电商领域积累下来的核心竞争力产品。Ha3 SQL 是在原有Ha3引…...

Linux(Web与html)

域名 DNS与域名&#xff1a; 网络是基于tcp/ip协议进行通信和连接的 tcp/ip协议是五层协议&#xff1a;应用层–传输层—网络层----数据链路层----物理层每一台主机都有一个唯一的地址标识&#xff08;固定的ip地址&#xff0c;用于区分用户和计算机。 ip地址&#xff1a;由…...

SpringBoot 底层机制分析[上]

文章目录 分析SpringBoot 底层机制【Tomcat 启动分析Spring 容器初始化Tomcat 如何关联Spring 容器】[上]搭建SpringBoot 底层机制开发环境Configuration Bean 会发生什么&#xff0c;并分析机制提出问题&#xff1a;SpringBoot 是怎么启动Tomcat &#xff0c;并可以支持访问C…...

电源控制--对数与db分贝

在控制理论中&#xff0c;"db"通常表示分贝&#xff08;decibel&#xff09;的缩写。分贝是一种用于度量信号强度、增益或衰减的单位。 在控制系统中&#xff0c;分贝常用于描述信号的增益或衰减。通常&#xff0c;增益以正数的分贝值表示&#xff0c;而衰减以负数的…...

LeetCode 1749. 任意子数组和的绝对值的最大值(前缀和)

题目&#xff1a; 链接&#xff1a;LeetCode 1749. 任意子数组和的绝对值的最大值 难度&#xff1a;中等 给你一个整数数组 nums 。一个子数组 [numsl, numsl1, …, numsr-1, numsr] 的 和的绝对值 为 abs(numsl numsl1 … numsr-1 numsr) 。 请你找出 nums 中 和的绝对…...

python爬虫相关

目录 初识爬虫 爬虫分类 网络爬虫原理 爬虫基本工作流程 搜索引擎获取新网站的url robots.txt HTHP协议 Resquests模块 前言&#xff1a; 安装 普通请求 会话请求 response的常用方法 简单案例 aiohttp模块 使用前安装模块 具体案例 数据解析 re解析 bs4…...

PAT(Advanced Level) Practice(with python)——1023 Have Fun with Numbers

Code N int(input()) D_N 2*N # print(Yes)if len(str(D_N))>len(str(N)):print(No) else:for s in str(D_N):if s not in str(N) or str(D_N).count(s)!str(N).count(s):print("No")breakelse:print(Yes) print(D_N)...

springboot vue 初步集成onlyoffice

文章目录 前言一、vue ts1. 安装依赖2. onlyoffice组件实现&#xff08;待优化&#xff09;3. 使用组件4. 我的配置文件 二、springboot 回调代码1. 本地存储 三、效果展示踩坑总结问题1问题2 前言 对接onlyoffice&#xff0c;实现文档的预览和在线编辑功能。 一、vue ts …...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...