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

news2024/12/24 20:31:32

目录

一、浏览器对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了。

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

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

相关文章

LOTO示波器实测过压保护芯片LP5300工作效果

过压保护电路是电子产品设置中经常要用到的&#xff0c;以前都是用分立元件搭的各种经典电路&#xff0c;最近LOTO虚拟示波器客户推荐了一款很便宜的集成的过压保护芯片LP5300&#xff0c;体积很小&#xff0c;使用简单&#xff0c;外接两个电容就可以了&#xff0c;下图是它的…

linux自定义网络访问规则

1.更改防火墙默认区域为trusted firewall-cmd --set-default-zonetrusted 2.新建一个zone&#xff0c;将想要访问本机80端口的ip&#xff0c;如&#xff1a;192.168.3.99 &#xff0c;添加的这个zone中&#xff0c;同时在这个zone中放行80端口。 firewall-cmd --permanent --ne…

django中使用bootstrap-datepicker时间插件

1、插件的下载 Bootstrap Datepicker是一款基 于Bootstrap框架的日期选择控件&#xff0c;可以方便地在Web应用中添加可交互的日期选择功能。Bootstrap Datepicker拥有丰富的选项和API,支持多种日期格式&#xff0c;可以自定义样式并支持各种语言。 Bootstrap Datepicker 依赖…

DolphinScheduler集群搭建详细笔记

1.DolphinScheduler Cluster部署 1.1 集群部署规划 集群模式下&#xff0c;可配置多个Master及多个Worker。通常可配置2~3个Master&#xff0c;若干个Worker。由于集群资源有限&#xff0c;此处配置一个Master&#xff0c;三个Worker&#xff0c;集群规划如下。 主机名ip服务…

Hybrid App 技术发展的趋势解读

Hybrid这个词&#xff0c;在App开发领域&#xff0c;相信大家都不陌生。Hybrid App是指介于web-app、native-app这两者之间的app&#xff0c;它虽然看上去是一个Native App&#xff0c;但只有一个UI WebView&#xff0c;里面访问的是一个Web App。Hybrid在移动领域的发展&#…

为什么要从 Splashtop Business Access 升级到 Enterprise?

远程工作只是偶尔为之的时代已经一去不复返了。它已成为一种战略必需品&#xff0c;使企业能够利用全球人才库&#xff0c;提供灵活的工作安排&#xff0c;并在不可预测的情况下确保业务连续性。 拥有安全、可靠、高效的远程访问解决方案已变得至关重要。Splashtop Business A…

【学习】若依源码(前后端分离版)之 “ 用户的权限注解”

大型纪录片&#xff1a;学习若依源码&#xff08;前后端分离版&#xff09;之 “ 用户的权限注解” 前言前端部分后端部分公开接口 结语 前言 接着来聊聊若依前后端分离版的权限注解吧。若依前后端分离版的权限注解是一种基于Spring Security和Vue的权限管理系统&#xff0c;它…

快速获得图像中像素值的小工具

之前项目中为了做lka中获得rgb图像信息&#xff0c;网上大多方案是确定相关的区域然后输出像素值&#xff0c;这个方法太麻烦&#xff0c;做了一个简单的使用鼠标点击图片某区域&#xff0c;然后直接在终端输出该区域的像素值。下面是源码&#xff1a; import cv2 import matp…

解析湖仓一体的支撑技术及实践路径

自2021年“湖仓一体”首次写入Gartner数据管理领域成熟度模型报告以来&#xff0c;随着企业数字化转型的不断深入&#xff0c;“湖仓一体”作为新型的技术受到了前所未有的关注&#xff0c;越来越多的企业视“湖仓一体” 为数字化转型的重要基础设施。 01 数据平台的发展历程…

kubernetes高性能存储-piraeus简介

piraeus简介 Piraeus 是面向 Kubernetes 的高性能、高可用性、简单、安全且与云无关的云原生存储解决方案&#xff0c;号称性能和稳定性都优于 Ceph/OpenEBS/Longhorn 等项目。Piraeus 对应的商业产品为LINSTOR 。 众所周知&#xff0c;本地存储具有高性能的优势&#xff0c;…

基于Python 简易实现接口测试自动化

目录 实现思路 统筹脚本 请求封装 日志封装 结果比对 结果邮件 用例获取及数据格式化 请求url转换 测试用例excel结构 测试报告 邮件接收结果 资料获取方法 实现思路 使用excel管理用例用例信息&#xff0c;requests模块发送http请求&#xff0c;实现了记录日志&…

科聪控制系统六大行业典型应用案例合集

01. 纺织行业 科聪移动机器人通用控制系统赋能无人接丝AGV实现丝盘自动化上下料 应用难点&#xff1a;无人接丝AGV是纺织行业无人工厂重要环节之一&#xff0c;这个环节对机器人到点精度要求非常高&#xff0c;无人接丝AGV的到位精度&#xff0c;必须确保“丝级”的准确无误&…

geeemap学习总结(2)——地图底图应用

1. 加载库中已有图层 import os os.environ[HTTP_PROXY] http://127.0.0.1:8001 os.environ[HTTPS_PROXY] http://127.0.0.1:8001 # 设置中心位置/地图层级/图层加载高度&#xff0c;加载图层 import geemap Mapgeemap.Map(center[40, 100], zoom4, height600) Map# 添加已经…

Javascript 正则

基本语法 定义 JavaScript种正则表达式有两种定义方式 构造函数 var regnew RegExp(<%[^%>]%>,g);字面量 var reg/<%[^%>]%>/g;g&#xff1a; global&#xff0c;全文搜索&#xff0c;默认搜索到第一个结果接停止i&#xff1a;ingore case&#xff0c;忽略…

Linux(进程地址空间)

进程地址空间 程序地址空间进程地址空间 程序地址空间 在Linux环境下&#xff0c;我们可以对上述程序空间地址进行验证&#xff1a; 运行程序&#xff0c;可以看到&#xff0c;我们就可以很好看出程序的地址空间的排布了&#xff1a; 进程地址空间 严格来说&#xff0c;我们…

免费商用图片素材网站,4K高清无水印。

推荐6个图片素材网站&#xff0c;免费下载&#xff0c;还可以商用&#xff0c;希望对大家有帮助。 菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库 网站主要是为新手设计师提供免费素材的&#xff0c;素材的质量都很高&#xff0c;类别也很多&#x…

NGINX组件(rewrite)

一、location匹配的规则和优先级&#xff08;*&#xff09; URI&#xff1a;统一资源标识符&#xff0c;是一种字符串标识&#xff0c;用于标识抽象的或者是物理资源&#xff1b;如&#xff1a;文件、图片、视频等 nginx中的URI匹配的是&#xff1a;网址”/“后的路径 如&…

17 spring项目——登录拦截器

经实验发现&#xff0c;当访问拦截器拦截的地址的时候都会经过拦截器。在拦截器中&#xff0c;返回true则放行&#xff0c;允许访问该地址&#xff1b;返回false&#xff0c;则拦截&#xff0c;不允许访问该地址&#xff0c;但可以在return前去设置要跳转的地址。 拦截器可以拦…

【二分】CF1623 C

Problem - 1623C - Codeforces 题意&#xff1a; 思路&#xff1a; 肯定是二分&#xff0c;我们去二分最小值&#xff0c;然后check的时候最小值要大于mid check的时候要让最小值尽可能大 注意到我们不需要去管最大值&#xff0c;只需要最小值尽可能大就好了&#xff0c;因…

Creo散热处理结构设计--阵列操作

问题描述&#xff1a; 在某一平面掏孔以散热&#xff0c;如何快速的绘制多孔并掏空处理 解决方式&#xff1a; 采用阵列操作。 1&#xff09;绘制圆、拉伸处理 2&#xff09;选择需要阵列的单元&#xff0c;选择阵列操作&#xff0c;在弹出的界面选择方向&#xff0c;按照…