WebRTC 基础
WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。允许网页直接连接
整体示意图
WebRTC整体架构
WebRTC 的实现流程
- ClientA首先创建PeerConnection对象,然后打开本地音视频设备,将音视频数据封装成MediaStream添加到PeerConnection中。
- ClientA调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。ClientA通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来,并通过Signal服务器发送给ClientB。
- ClientB接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象,通过PeerConnection的SetLocalDescription的方法保存该应答SDP对象并将它通过Signal服务器发送给ClientA。
- ClientA接收到ClientB发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来。
- 在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)。
- 当ClientA收集到Candidate信息后,PeerConnection会通过OnIceCandidate接口给ClientA发送通知,ClientA将收到的Candidate信息通过Signal服务器发送给ClientB,ClientB通过PeerConnection的AddIceCandidate方法保存起来。同样的操作ClientB对ClientA再来一次。
-
这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输。
信令服务器(Signaling server)
1.用来控制通信开启或者关闭的连接控制消息
2.发生错误时用来彼此告知的消息
3.媒体流元数据,比如像解码器、解码器的配置、带宽、媒体类型等等
4.用来建立安全连接的关键数据
5.外界所看到的的网络上的数据,比如P地址、端口等
6.信令服务器并不需要理解和解释信令数据内容。虽然它基于 SDP但这并不重要:通过信令服务器的消息的内容实际上是一个黑盒。
how
使用Nodejs下的socket.io库来实现WebRTC信令服务器
ICE服务器
可以分为帮助两个客户端打洞建立 P2P 连接的 STUN 服务器,还有如果连不通就直接转发的 TURN 服务器。ICE 的信息叫 Candidate,可以通过 SDP 交换,或者通过 Trickle。
WebRTC连接方式
- 通过本地直接连接(开启多个浏览器页面对话)
- 通过公共ip地址(STUN服务器,获取外网地址,通过NAT墙)
-
通过WebRTC TURN服务器路由连接媒体(传递音视频数据)
WebRTC 多方通信
- Mesh(Multiple Direct Connections)
- MCU(Multipoint Conferencing Unit)
-
SFU(Selective Forwarding Unit)
Mesh
网状结构
只能支持4-6人左右
没有中心节点,实现很简单
MCU
由一个服务器和多个终端组成一个星形结构
浏览器压力小,服务器压力较大
SFU
由一个服务器和多个终端组成一个星形结构(不对音视频进行混流)
NAT(Network Address Translation)
NAT又称网络掩蔽、IP掩蔽在计算机网络中是一种在IP数据包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术
- 优先STUN (Session Traversal Utilities for NAT),NAT会话穿越应用程序
-
备选TURN (Traversal Using Relay NAT) ,中继NAT实现的穿透
SDP
SDP(Session Description Protocol) 是一种会话描述协议,基于文本,其本身并不属于传输协议,需要依赖其它的传输协议(比如 SIP 和 HTTP)来交换必要的媒体信息,用于两个会话实体之间的媒体协商。
//SDP协议的具体格式如下,分为两部分:会话描述和媒体描述。其中带星号(*)的表示可选。
Session description
v= (protocol version)
o= (originator and session identifier)
s= (session name)
i=* (session information)
u=* (URI of description)
e=* (email address)
p=* (phone number)
c=* (connection information -- not required if included in all media)
b=* (zero or more bandwidth information lines)
[...One or more time descriptions ("t=" and "r=" lines)]
z=* (time zone adjustments)
k=* (encryption key)
a=* (zero or more session attribute lines)
[...Zero or more media descriptions]
Time description
t= (time the session is active)
r=* (zero or more repeat times)
Media description, if present
m= (media name and transport address)
i=* (media title)
c=* (connection information -- optional if included at session level)
b=* (zero or more bandwidth information lines)
k=* (encryption key)
a=* (zero or more media attribute lines)
//caller生成本地描述信息
const offer = await peerConnection.createOffer();
//caller设置本地描述信息
await peerConnection.setLocalDescription(offer);
//caller发送本地描述信息至远端
const signalServer = new WebSocket('ws://[xxx.signal.com](http://xxx.signal.com/)');
signalServer.send({
type: 'offer',
data: offer,
});
//callee设置远端描述信息
await peerConnection.setRemoteDescription(offer);
//callee生成本地应答描述信息
const answer =await peerConnection.createAnswer();
//callee设置本地描述信息
await peerConnection.setLocalDescription(answer);
ICE
交互式连接建立。它是一种端到端交互的技术,可以让两个终端相互知道对方的公网IP,可以不借助一个公网server完成端到端(Peer to peer,P2P)的通信。
当各端调用 setLocalDescription 后,WebRTC就开始建立网络连接,主要包括收集candidate、交换candidate和按优先级尝试连接,该过程被称为ICE(Interactive Connectivity Establishment,交互式连接建立)。其中每个 candidate 都包含IP地址、端口、传输协议、类型等信息。
iceConnectionState
"new": 建立ICE连接
ICE 代理正在搜集地址或者等待远程候选可用。
"checking": 收集候选
ICE 代理已收到至少一个远程候选,并进行校验,无论此时是否有可用连接。
同时可能还在继续收集候选。
"connected": 匹配到可用候选
已为连接的所有组件找到可用的本地和远程候选配对,并且已建立连接。
此时仍然会继续测试远程候选以便发现更优的连接。同时可能在继续收集候选。
"completed": 匹配完成,连接建立
ICE代理已经发现了可用的连接,不再测试远程候选。
"failed":没有合适候选
ICE候选测试了所有远程候选没有发现匹配的候选。
也可能有些候选中发现了一些可用连接。
"disconnected":网络波动或者串流断开
RTPeerConnection至少有一个组件连接失败。
"closed": 断开ICE
ICE代理关闭,不再应答任何请求。
STUN
Session Traversal Utilities for NAT,是一种技术可以让位于NAT后的设备可以查找自己的公网IP
PeerConnectionClient
PeerConnectionClient类,他的作用是与信令服务器(server)来进行TCP通信。它可以通过在两台机器间生成 Session Description 的数据交换协议来实现。呼叫方发送一个 offer(请求),被呼叫方发出一个 answer(应答)来回答请求。双方 - 呼叫方以及被呼叫方,最开始的时候都要建立他们各自的 RTCPeerConnection 对象。
MediaStream
MediaStream API 是连接 WebRTC API 和底层物理流的中间层,webRTC将音视频经过Vocie / Video engine进行处理后,再通过MediaStream API给暴露给上层使用。MediaStream
接口是一个媒体内容的流.。一个流包含几个轨道,比如视频和音频轨道。
通过 navigator.getUserMedia()
获取MediaStream
RTCDataChannel
RTCDataChannel 接口是WebRTC API的一个功能,可以让您在两个对等体之间打开一个通道,您可以通过该通道发送和接收任意数据。
// 创建 let Channel = RTCPeerConnection.createDataChannel('messagechannel', options);
// messagechannel 可以看成是给 DataChannel 取的别名,限制是不得超过65,535 字节。 // options 可以设置一些属性,一般默认就好。
// 接收 RTCPeerConnection.ondatachannel = function(event) {let channel = event.channel;
}
RTCPeerConnection sample
- getUserMedia 获取音频和视频流
- RTCPeerConnection
pc = new RTCPeerConnection(null);
pc.onaddstream = gotRemoteStream;
pc.addStream(localStream);
pc.createOffer(gotOffer);function gotOffer(desc) {
pc.setLocalDescription(desc);
sendOffer(desc);
}function gotAnswer(desc) {
pc.setRemoteDescription(desc);
}function gotRemoteStream(e) {
attachMediaStream(remoteVideo, e.stream);
}
通过offer和answer交换SDP描述符
-
createOffer()
-
setLocalDescription()
-
setRemoteDescription()
-
createAnswer()
-
setLocalDescription()
相关知识点
-
WebSocket / XMLHttpRequest
-
FFmpeg
-
MediaStreamTrace
-
RobotJs
-
ICE (Interactive Connectivity Establishment)
-
SDP
-
video.js