导言
WEBRTC 于 2021 年 1 月被 W3C 和 IETF 发布为正式规范后,现已运用在了许多方面,有些还做出了很不错的产品。下面是最近学习 WEBRTC 进程中一些浅陋的知识总结,如有错误,欢迎指正。全文阅览大约需求 15-20 分钟。
全文将按如下的流程翻开:
- 介绍一下 WEBRTC 的前史和目标
- 简略讲解几个要害概念和作业流程
- 常用的 API 和示例代码
- 运用场景
WebRTC 是什么?
WebRTC 是 Web 实时通讯(Real-Time Communication)的缩写,是由一家名为 Gobal IP Solutions(简称 GIPS)的瑞典公司开发的。Google 在 2011 年收购了 GIPS,并将其源代码开源。然后又与 IETF 和 W3C 的相关规范组织协作,以保证职业达成共识。其间:
- W3C 组织:定义浏览器 API。
- IETF 规范组织:定义其所需的协议,数据,安全性等手法。
简略来说,WebRTC 是一个能够在 Web 运用程序中完成音频,视频和数据的 实时通讯的开源项目。
在实时通讯中,音视频的搜集和处理是一个很复杂的进程。比如音视频流的编解码、降噪和回声消除等,可是在 WebRTC 中,这一切都交由浏览器的底层封装来完结。咱们能够直接拿到优化后的媒体流,然后将其输出到本地屏幕和扬声器,或许转发给其对等端。
咱们能够在不需求任何第三方插件的状况下,完成一个浏览器到浏览器的点对点(P2P)衔接,然后进行音视频实时通讯。
WEBRTC 所用的技能大多现已完成了,WEBRTC 是把这些技能组合了起来。也能够说 WebRTC 是一组其他技能的集合体。
作业流程是什么样?
简略介绍后,我想你的脑海中现已大约知道 WEBRTC 是做什么的了,下面咱们一起探究一下这个进程中发生了什么。咱们能够将其分为四个进程:
- 信令(Signaling)
- 衔接(Connecting)
- 安全加密(Securing)
- 通讯(Communicating)
这四个进程顺次发生。上一个进程有必要 100% 成功,随后的进程才干开端。
信令(Signaling)
首要,需求了解的一个概念是信令。
信令是在两个设备之间发送操控信息以确认通讯协议、信道、媒体编解码器和格式以及数据传输方法以及任何所需的路由信息的进程。
为什么需求了解这个概念?
尽管 WEBRTC 是 P2P 的,但并不代表不需求服务端的参与。当一个 WebRTC Agent 被创立时,它对其他的对等节 一无所知。它不知道它将与谁联络,也不知道它们将发送些什么!所以在信令阶段需求双向通讯服务辅助信息交流。 交流信令音讯后,WebRTC Agent 才干够直接彼此通讯。
格式
信令 的格式依据 SDP (Session Description Protocol) 规范,例如:
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
-------------- 下面的内容为字段解说 ---------------
v - Version,版别,版别,应等于 0。
o - Origin,源,包括一个唯一 ID,用于从头洽谈。
s - Session Name,会话名称,应等于-。
t - Timing,时间,应等于 0 0。
m - Media Description(m=<media> <port> <proto> <fmt> ...),媒体描绘,下面有详细阐明。
a - Attribute,属性,一个自在文本字段,这是 WebRTC 中最常见的行。
c - Connection Data,衔接数据,应等于 IN IP4 0.0.0.0。
-
v
,o
,s
,c
,t
尽管被定义,但他们不对 WebRTC 会话产生影响。 -
上面的代码里有三个媒体描绘。第一个是
audio
即音频类型,数据映射到 PCMU 编解码器。后两个是video
即视频类型,分别映射到 H261 和 MPV 编解码器。下图是一个实践的示例:
内容
信令 的内容包括以下几个方面:
-
操控音讯:用于设置、翻开、关闭通讯通道并处理错误。
-
为了树立衔接所需的信息:设备间能够彼此交谈所需的 IP 寻址和端口信息。
-
媒体能力洽谈:交互两边能够了解哪些编解码器和媒体数据格式?这些都需求在 WebRTC 会议开端之前达成共同。
传输
信令 的传输没有规范,能够挑选 Websocket 或许 xhr 乃至电子邮件。假如你乐意承受推迟,乃至能够把信令数据打印出来,飞鸽传书给另一个人,等对方手动输入,并用相同的方法回来给你信令数据。
流程
信令的运用和传输流程如下图所示,假如 Amy 向 Bob 发送了一个音视频邀约:
- 呼叫端创立 Offer 信息,并存储到本地,再发送给信令服务器,信令服务器转发给接纳端
- 接纳端收到 Offer 后,先存储远端描绘,然后创立 Answer 信息。相同,先保存 Answer 到本地,再回来给信令服务器,信令服务器转发给呼叫端。
- 呼叫端拿到 Answer 后,再设置到远端描绘
什么是 Offer 和 Answer?
WebRTC 运用 Offer/Answer 模型。这指的是,一个 WebRTC Agent 宣布 “Offer” 以开端呼叫,假如另一个 WebRTC Agent 乐意承受 “Offer” 的内容,它会响应 “Answer”。
这使得应对者有机会回绝媒体描绘中的某些不支撑的编解码器,也是两个 peer 互相了解他们期望交流何种格式的方法。
现在,两个 WebRTC Agent 知道足够的详细信息能够测验彼此衔接了。
衔接(Connecting)
接下来,WebRTC 将运用另一种成熟的技能,称为 ICE(交互式衔接树立)。
ICE 答应在两个 Agent 之间树立衔接。这些 Agent 能够在同一网络上,也能够在世界的另一端。ICE 是无需中心服务器即可树立直接衔接的处理方案。
已然要直接树立衔接,就必然需求处理例如 NAT 地址转换、防火墙、网络协议不同、IP 版别不平等问题。ICE 运用STUN 协议以及 TURN 协议来进行穿越。
NAT 穿越
现在的网络设备,许多是依据 NAT 技能运用同一个公网 IP 和不同的端口对外供给拜访通道的。假如需求树立直接衔接,就需求知道对方的公网 IP 和端口,以及对方的网络类型,比如是直接在公网可拜访,仍是经过了 NAT 设备。
STUN Server 做了什么?
-
承受客户端的恳求,而且把客户端的公网 IP、Port 封装到 ICE Candidate 中。
-
经过一个复杂的机制(后文会讲),得到客户端的 NAT 类型。
简而言之,便是向公网的一个 STUN 服务器发送 Binding Request,公网的这个服务器能看到你的公网 IP 和端口,并测试你是否在 NAT 设备后面,以及 NAT 的类型。
判别 NAT 类型
RFC3489 中将 NAT 的完成分为四大类:
Full Cone NAT | 完全锥形 NAT | 无论什么IP地址拜访,都不会被NAT墙掉(这种基本很少) |
---|---|---|
Restricted Cone NAT | 约束锥形 NAT | 了解为 IP 约束,Port不约束 |
Port Restricted Cone NAT | 端口约束锥形 NAT, | IP+Port 约束 |
Symmetric NAT | 对称 NAT | IP+Port 约束,一起对外的公网Port是不停的变化的比如A是一个对称NAT,那么A给B发信息,经过NAT映射到一个Port:10000,A给C发信息,经过NAT映射到一个Port:10001,这样会导致一个问题,咱们服务器底子无法和谐进行NAT打洞。 |
假定 B 是 客户端 ,C 是 STUN 服务器,C 有两个 IP 分别为 IP1 和 IP2(至于为什么要两个IP,接着往下看):
第一步:判别 客户端 是否在 NAT 后
B 向 C 的 IP1:PORT1
端口发送一个 UDP 包。C 收到这个包后,会把它收到包的源 IP 和 PORT 写到 UDP 包中,然后把此包经过 IP1:PORT1
发还给 B。这个 IP 和 port 也便是 NAT 的外网 IP 和 PORT。
B 收到后,拿回来的 IP 和自己的 IP 对比一下,假如共同,阐明 B 便是用的公网 IP,没有用 NAT,假如不共同则持续勘探防火墙类型。
第二步:判别是否处于Full Cone Nat 下:
B 仍是向 IP1:PORT1
端口发送恳求,可是要求 C 用 IP2:PORT2
回来成果。
假如 B 收到了,阐明 NAT 来者不拒,不对数据包进行任何过滤,这也便是STUN规范中的 Full Cone NAT。
第三步:判别是否处于对称 NAT 下
依据对称 NAT 的规则,当意图地址的 IP 和 PORT 有任何一个改变,那么 NAT 都会从头分配一个port运用。所以 B 再向 IP2:PORT2
恳求,回来的端口和第一次假如不共同,阐明便是对称 NAT。
第四步:判别是处于 Restrict Cone NAT 仍是 Port Restrict NAT 之下
B 向 IP1:PORT1
发恳求,要求 C 换一个端口回来。
假如 B 收到了,那也就意味着只需 IP 相同,即使 PORT 不同,NAT 也答应 UDP 包经过。显然这是 Restrict Cone NAT。假如没收到,意味着 IP 和 PORT 都有必要相同,便是 Port Restrict NAT.
完结了这些 STUN Server 就会把这些基本信息发送回客户端,然后依据 NAT 类型,来判别是否需求 TURN 服务器和谐进行下一步作业。
当你的两个 peer 的 NAT 类型不兼容,或许两边运用不同协议时,就需求运用 TURN server,进程如上图所示。TURN server 也能够被用于维护隐私的意图,假如经过 TURN server 进行一切通讯,客户的实在地址在对端是被隐藏的。
候选地址挑选
ICE 经过上面讲到的流程来找出两个 peer 之间一切可能的路由,这些路由被称为 Candidate Pair(候选地址对)
,也便是本地地址和远程地址的配对。这便是 STUN 和 TURN 在 ICE 中发挥作用的地方。这些地址能够是你的本地 IP 地址,NAT 映射
或中继传输地址
。通讯两边需求搜集它们要运用的一切地址,交流这些地址,然后测验衔接。
通常来说,发送 offer 的 peer 是操控中
的一方。操控中
的 Agent 和受控中
的 Agent 都开端在每个候选地址对上发送流量数据。
每个收到流量数据的候选地址对
,会被提升为有用候选地址
对。
接下来,操控中
的 Agent 将指定一个有用候选地址
对,这便是提名候选地址对
。
然后,操控中
的 Agent 和受控中
的 Agent 再测验进行一轮双向通讯。假如成功,则提名候选地址对
将成为选定的候选地址对
!它将被用于后面的会话中。
安全加密(Securing)
现在咱们有了双向通讯(依据 ICE),咱们需求树立安全的通讯,这是依据 WebRTC 前已有的两种协议完结的。
第一个协议是 DTLS(数据报传输层安全性),即依据 UDP 的 TLS。
第二种协议是 SRTP(安全实时传输协议)。
首要,WebRTC 经过在 ICE 树立的衔接上进行 DTLS 握手来进行衔接。与 HTTPS 不同,WebRTC 不运用中心授权来颁布证书。相反,WebRTC 仅仅判别经过 DTLS 交流的证书是否与经过信令共享的签名相符。然后,此 DTLS 衔接能够被用于传输 DataChannel 音讯。
WebRTC 运用两个预先存在的协议,数据报传输层安全(Datagram Transport Layer Security / DTLS)和 安全实时传输协议(Secure Real-time Transport Protocol / SRTP)。
DTLS 与 TLS 的区别仅在与其运用 UDP 而不是 TCP 作为其传输层。这也意味着 DTLS 协议有必要处理不可靠的数据传输。SRTP 是专为安全的交流媒体数据而设计的。相对于 DTLS 而言,运用 SRTP 对传输媒体数据有一些优化。
通讯(Communicating)
现在,咱们有了两个具有安全的双向通讯功用的 WebRTC Agent。让咱们开端通讯!跟前面一样,咱们运用两个现有的协议:RTP(实时传输协议)和 SCTP(流操控传输协议)。咱们运用 RTP 来交流用 SRTP 加密过的媒体数据,运用 SCTP 发送和接纳那些用 DTLS 加密过的 DataChannel 音讯。
全体流程图
常用 API
WebRTC 供给了一些 API 供咱们运用,在实时音视频通讯的进程中,咱们首要用到以下三个:
- getUserMedia:获取音频和视频流(MediaStream)
- RTCPeerConnection:点对点通讯
- RTCDataChannel:数据通讯
简略看一下三个 API 的运用方法:
GetUserMedia
用来获取设备的媒体流(即 MediaStream)。它能够承受一个约束目标 constraints 作为参数,用来指定需求获取到什么样的媒体流。此要求能够非常广泛(音频和/或视频),也能够非常具体(最低相机分辨率或确切设备 ID 等)。
navigator.mediaDevices.getUserMedia({ audio: true, video: true }) // 一起获取到音频和视频 .then(stream => { // 获取到优化后的媒体流 let video = document.querySelector('#rtc');
video.srcObject = stream;
}).catch(err => {});
RTCPeerConnection
创立点对点衔接的 API,是咱们完成音视频实时通讯的要害。创立时,需求传入一个配置目标,包括 iceServers 字段
new RTCPeerConnection({
iceServers: [
{ url: "stun:stun.l.google.com:19302" }, // 谷歌的公共服务
{
urls: "turn:***",
credential: "***",
username: "***",
},
],
});
RTCDataChannel
创立数据通道,用来交流任意类型的数据
let dataChannel = pc.createDataChannel("MyApp Channel");
dataChannel.addEventListener("open", (event) => {
beginTransmission(dataChannel);
});
代码示例
下面是一个简略的 WRBRTC 视频通话示例,代码语言为 JavaScript,安装依赖后启动,会看到下图所示的日志,能够参照上面所讲的内容对照了解全体流程:
有哪些运用场景?
电话视频会议
WebRTC 为媒体供给拥塞操控和自适应比特率,跟着网络条件的变化,用户仍将获得最佳体会,开发人员不必编写任何其他代码来处理这些状况。
由于能够对视频做处理,所以也支撑例如增加滤镜、布景替换、AR 等功用。
Facebook Messenger、Discord、Amazon Chime、Google Meet/Hangout/Duo,都是依据 WebRTC 的视频通讯东西、视频会议运用。
音视频发布、消费渠道
浏览器中的 WebRTC 使得用户能够轻松发布视频。这样用户不需求下载新的客户端。 任何具有 Web 浏览器的渠道都能够发布视频。发布者能够发送多个音轨 / 视频流,并能够随时对其进行修正或删去。传统协议中每个衔接只答应一个音频或一个视频流,与之相比,这是一个巨大的改进。
在线白板、投屏
使用 captureStream
API 能够直接捕获 canvas 的画面,然后经过 WEBRTC 以流的方式传输给对方,就很容易的完成了在线白板功用。
this.localstream = canvasDom.captureStream();
使用 getDisplayMedia
API 能够直接捕获其他浏览器 tab、窗口或屏幕的画面(例如飞书投屏时的挑选),下面是核心代码:
navigator.mediaDevices.getDisplayMedia(options)
.then(handleSuccess, handleError);
handleSuccess(stream) {
video.srcObject = stream;
}
云游戏
2020 年,云游戏现已上线了。它的完成有赖于 WebRTC。 Stadia(Google 的云游戏渠道)已于 2019 年末推出,但 2020 年初才正式在浏览器得以支撑。其云游戏搭载 VP9,供给 4k、HDR 图画和环绕声体会。这些都会经过 WebRTC 进行传输。