《WebRTC通话原理》

前言

为什么写这篇文章?

对于 WebRTC 的了解,相信大部分👨‍🎓始终停留在使用上,可能了解了如 getUserMedia、createAnswer、setRemoteDescription 等 API 的使用,却不了解它的意义,对 WebRTC 依然是一知半解的状态。这篇文章更多是帮助大家建立一个完整的知识体系,对整个连接建立过程有更深刻的理解。

WebRTC 通信实践

我们从实践出发,简单梳理一遍WebRTC整个连接的建立过程。

创建 RTCPeerConnection 对象

RTCPeerConnection对象是WebRTC的核心,它是WebRTC暴露给用户的统一接口,其内部由多个模块组成,如网络处理模块、服务质量模块、音视频引擎模块,等等。通过它可以轻松地完成端到端数据的传输。在建立WebRTC连接的第一步我们得先创建一个RTCPeerConnection对象。实现代码如下所示:

js 复制代码
const pc = new RTCPeerConnection();

RTCPeerConnection绑定要传输的音视频数据

通过getUserMedia()接口采集音视频数据,将采集到的数据与RTCPeerConnection对象绑定到一起。只有让RTCPeer Connection拿到音视频数据,它才能将其发送出去。实现代码如下所示:

js 复制代码
const stream = navigator.getUserMedia({ audio: true, video: true })
stream.getTracks().forEach((track) => {
    pc.addTrack(track, stream);
})

媒体协商

当RTCPeerConnection对象与音视频绑定后,紧接着需要进行媒体协商。什么是媒体协商呢?比如说,你默认使用的编码器是VP8,要想与对方通信,还需要知道对方是否可以解码VP8的数据。如果对方不支持VP8解码,那你就不能使用这个编码器。媒体协商的目的在于协商双方都能编解码的媒体格式。整个协商过程共8步。链路比较长代码不方便描述,下面图示描述一下这个过程: 图中第❽步完成后,整个媒体协商过程就算完成。虽说步骤分了8步,但是其实就是做了一个事情,交换 SDP。

tips: 在 WebRTC 中媒体协商过程使用 SDP 协议描述媒体信息, 有时我们会把这个过程称为交换SDP

ICE

当媒体协商完成后,WebRTC就开始建立网络连接了,其过程称为ICEICE是在各端调用setLocalDescription()接口后就开始了。WebRTCRTCPeerConnection对象中提供了一个事件,即onicecandidate。通过设置回调函数就可以获得WebRTC底层收集到的所有candidate了。同时,还可以在该函数中将收集到的Candidate发送给对端。代码如下所示:

js 复制代码
pc.onicecandidate = (e) => {
    if (e.candidate) {
         // 将 candidate 通过信令服务器传给远端
    }
}

用下面图示描述一下这个过程:

设备双方接收到Candidate后,会与本地的Candidate形成CandidatePair(即连接候选者对)。有了CandidatePair,WebRTC就可以开始尝试建立连接了。

tips:这里需要注意的是,Candidate的交换不是等所有Candidate收集好后才进行的,而是边收集边交换。一旦WebRTC发现其中有一个可以连通的CandidatePair时,它就不再进行后面的连接尝试了,但发现新的Candidate时仍然可以继续进行交换。

音视频渲染

连接一旦建成,音视频数据就开始源源不断地由发送端发送给接收端。WebRTC给我们提供了一个接口,即RTCPeerConnection对象的ontrack()事件。每当有远端的音视频数据传过来时,ontrack()事件就会被触发。因此你只需要给ontrack()事件设置一个回调函数,就可以拿到远端的MediaStream了。在回调函数中,需要将获得的MediaStream对象赋值给标签,这样就能在页面播放音视频了。代码如下所示:

js 复制代码
pc.ontrack = (e) => {
    videoElement.srcObject = e.streams[0];
}

总结

WebRTC SDP详解

WebRTC引入SDP来描述媒体信息,用于媒体协商时决定双方是否可以进行通信。SDP作为信令系统的一部分,驱动着整个WebRTC的运转,掌握SDP的内容,能帮助你更好地理解WebRTC的运行机制。

SDP 示例

js 复制代码
v=0
o=- 20518 0 IN IP4 203.0.113.1
s=-
t=0 0
a=group:BUNDLE audio video
m=audio 5004 RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 203.0.113.1
a=rtcp:5005 IN IP4 203.0.113.1
...
m=video 5006 RTP/SAVPF 100 101 107 116 117 
c=IN IP4 203.0.113.1 
a=rtcp:5007 IN IP4 203.0.113.1
...

仔细观察代码结构你会发现所有的描述都以行为单位,描述格式如下:

js 复制代码
<type> = <value>

如果你之前从未接触过SDP,看这段代码时一定会觉得很茫然。实际上这段代码的含义非常简单,由两部分构成,即会话描述和媒体描述。其中,第1∼4行代码称为会话描述,第5行代码开始称为媒体描述。

在整个SDP中,只能有一个会话描述,而媒体描述可以有多个。通常SDP中包含两个媒体描述:一个音频媒体描述,一个视频媒体描述。以下图示为SDP的整体结构: 之所以把SDP单独拎出来讲,主要是想让大家清楚 WebRTC 中很多信息/参数都是从 SDP 中获取的,不仅仅是媒体参数,如果你想深入 WebRTC 的处理逻辑,对 SDP 熟悉掌握必不可少。SDP 随简单却包含着 WebRTC 安全机制、服务质量中重要的信息,有兴趣的读者可以深入了解。

WebRTC ICE详解

上文中我们提到了收集和交换Candidate的方式。你可能会疑惑:candidate是什么,WebRTC是如何从多个Candidate中选择出适合连接的Candiate的呢?

什么是candidate?

比如我们想连接某台服务器,一定要知道这台服务器的一些基本信息,如服务器的IP地址、端口号以及使用的传输协议。只有知道了这些信息,才能与这台服务器建立连接。而Candidate正是WebRTC用来描述它可以连接的远端的基本信息,因此它是至少包括{address,port,protocol}三元组的一个信息集。

Candidate 的种类与优先级

ICE中使用的Candidate有四种,它们的优先级由高到低分别为host、srflx、prflx、relay。WebRTC进行一对一音视频通信时,就是按照这个次序尝试建立连接的。

tips:srflx 与 prflx 的候选者的区别在于应对不同的 NAT 环境

ICE 策略

WebRTC的ICE默认机制会选择最好的链路传输音视频数据,即如果通信的双方在同一网段内,则优先使用内网链路;如果通信的双方不在同一网段,则优先使用P2P;当以上方式都无法连通时,则使用relay服务进行中转。

举个🌰子

如果设备A和B是在同一局域网下,那么它们会通过host类型的Candidate可以在内网建立起连接。当连接成功后,音视频数据就可以源源不断地从一方流向另一方了。

如果不在同一局域网,那么会尝试使用 srflx、prflx 类型的candidate进行P2P连接,当无法连通时,则用 relay 类型,即采用服务中转的方式进行连接。

相关推荐
北城青3 小时前
WebRTC Connection Negotiate解决
运维·服务器·webrtc
天天讯通7 小时前
网页WebRTC电话和软电话哪个好用?
webrtc
弱冠少年7 小时前
WebRTC入门
webrtc
limingade5 天前
手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告)
android·物联网·计算机外设·音视频·webrtc·信号处理
余生H5 天前
拿下奇怪的前端报错:某些多摄手机拉取部分摄像头视频流会导致应用崩溃,该如何改善呢?
前端·javascript·webrtc·html5·webview·相机
Liveweb视频汇聚平台7 天前
如何使用 WebRTC 获取摄像头视频
音视频·webrtc
Crazy learner11 天前
WebRTC中的维纳滤波器实现详解:基于决策导向的SNR估计
人工智能·webrtc·语音识别
Rookie也要加油12 天前
01_WebRtc_一对一视频通话
笔记·学习·音视频·webrtc
Liveweb视频汇聚平台12 天前
国标GB28181视频融合监控汇聚平台的方案实现及场景应用
音视频·webrtc·实时音视频·h.265·视频编解码
太上绝情12 天前
webrtc-candidate形成分析
webrtc