WebRTC 学习
介绍
WebRTC(Web Real-Time Communications)是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC 包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。
基于 WebRTC API 构建的协议
ICE:交互式连接创建,是一个允许你的浏览器和对端浏览器建立连接的协议框架。两个节点需要交换 ICE 候选来协商他们自己具体如何连接。每一个 ICE 候选描述一个发送者使用的通信方法,每个节点按照他们被发现的顺序发送候选并且保持发送直到退出,即使媒体数据流已经开始传递也要如此。这个框架的算法是寻找最低等待时间的路径去连接两端,ICE 通过使用以下几种技术完成上述工作。
- STUN:NAT 的会话穿越功能,是允许位于 NAT 后的客户端找出自己的公网地址,判断出路由器阻止直连的限制方法的协议。
- NAT:网络地址转换协议,用来给私网设备映射一个公网的 IP 地址,但是一些路由器严格的限定了谁能连接内网设备。这种情况下需要专项 TURN 协议。
- TURN:一些路由器使用一种“对称型 NAT”的 NAT 模型。这意味着路由器只接受和对端先前建立的连接(就是下一次请求建立新的连接映射)。NAT 的中继穿越方式通过 TURN 服务器中继(暂时理解为转发)的方式绕过“对称型 NAT”。
- SDP:会话描述协议。是一个多媒体连接内容的协议。
WebRTC 连接
上面介绍了协议,下面介绍如何相互交互使用上述协议,以便在对等体之间创建连接和传输数据或者多媒体。
提议/应答和信号通道
WebRTC 中间无法创建没有服务器的某种连接,换句话说,WebRTC 虽然是点对点通信(peer to peer),但是点之间在创建 WebRTC 通道建立连接的过程中需要通过某种方式交换信息(交换 SDP)。
将作为连接发起者的同伴 A 将创建一个提议。然后他们将使用所选择的信号通道将此提议发送给对等体 B. 对等体 B 将从信号通道接收提议并创建应答。然后,它们将沿着信号通道发送回对等体 A。
会话描述(SDP)
WebRTC 连接上的端点配置称为会话描述,该描述包括要发送的媒体类型、格式、正在使用的传输协议,端点(peer)的 IP 地址和端口以及描述媒体传输断电所需的其他信息的信息。使用会话描述协议(SDP)来交换和存储该信息。
当一个用户对另一个用户启动 WebRTC 调用的时候,将创建一个叫做**提议(offer)的特定描述。该描述包含有关呼叫者建议的呼叫配置的所有信息。接受者然后用应答(answer)进行响应,这是他们对呼叫结束的描述。以这种方式,两个设备彼此共享以便减缓媒体数据所需的信息。该交换是使用上面提到的交互式连接(ICE)**处理的。这是一种协议。
然后,每个对等端保持两个描述:
- 描述本身的本地描述
- 描述呼叫远端的远程描述
在首次建立呼叫时,还可以在呼叫格式或其他配置需要更改的任何时候执行提议/应答过程。无论是新呼叫还是重新配置现有的呼叫,这些都是交换提议和回答所必需的步骤。
- 呼叫者捕捉本地媒体(比如
navigator.mediaDevices.getDisplayMedia
、navigator.mediaDevices.getUserMedia
) - 呼叫者创建一个
RTCPeerConnection
并调用RTCPeerConnectiuon.addTrack()
,注:该方法将一个新媒体音轨添加到一组音轨中,这些音轨将被传输至另一个对灯点,该方法返回将用于传输媒体数据的RTCRtpSender对象。 - 呼叫者调用
RTCPeecConnection.createOffer()
方法来创建一个提议(offer)。 - 呼叫者调用
RTCPeerConnection.setLocaleDescription()
方法将提议设置为本地描述(连接的本地描述)。 - 设置本地描述后,呼叫者请求
STUN
服务创建 ICE 候选(ice candidates)。 - 呼叫者通过信令服务器将提议(offer)传递至本次呼叫的预期接受者(被呼叫者,也就是接收者)。
- 接收者收到提议并且调用
RTCPeerConnection.setRemoteDescription()
方法将其记录为远程描述(也就是连接另一端的描述)。 - 接收者做一些可能需要的步骤结束本次呼叫:捕捉本地媒体,然后通过
RTCPeerConnection.addTrack()
方法添加到连接中。 - 接收者通过
RTCPeerConnection.createAnswer()
创建一个应答。 - 接收者调用
RTCPeerConnection.setLocalDescription()
方法将应答设置为本地描述,此时接收者已经获知连接双方的配置了。 - 接收者通过信令服务器将应答传递到呼叫者。
- 呼叫者收到应答。
- 呼叫者调用
RTCPeerConnection.setRemoteDescription()
方法将应答设为远程描述。如此,呼叫者也就获知连接双方的配置了。
注:呼叫者在发出呼叫后以及接收者接收呼叫生成 pc 后应该注册监听 onicecandidate 事件监听新的 ice 候选,一旦监听到有新的 ice 候选就应该发送给对方。如果是双方的媒体流通信就应该监听 pc.ontrack 事件监听对方推过来的媒体流,并做处理。
什么是 ICE 候选地址
除了交换关于媒体的信息 (上面提到的 Offer / Answer 和 SDP ) 中,对等体必须交换关于网络连接的信息。这被称为 ICE 候选者,并详细说明了对等体能够直接或通过 TURN 服务器进行通信的可用方法。通常,每个对点将优先提出最佳的 ICE 候选,逐次尝试到不佳的候选中。理想情况下,候选地址是 UDP(因为速度更快,媒体流能够相对容易地从中断恢复 ),但 ICE 标准也允许 TCP 候选。
注:WebRTC 连接信令交换过程介绍请查看 MDN 官方文档
数据通道dataChannel
数据通道dataChannel(RTCDataChannel
)是WebRTC的一个功能,我们可以使用该功能在两个对等体之间打开一个数据通道,然后使用该数据通道发送任意数据(甚至可以发送文件)。
实际使用举例
下面就以实现一对一视频通话的demo场景来学习WebRTC技术,我们先整理在两个Web页面之间通过WebRTC技术实现视频通话的流程:
- 两个对等体之间需要建立通信(比如连接至同一个WebSocket服务器,因为我们需要服务器来交换信令等等)。
- 连接信令服务器并且创建RTCPeerConnection。
- 注册事件,比如:ice候选更新后需要发送给对方,收到对方的流需要处理,创建或者监听dataChannel等等。
- 发送方先拿到视频流(这里以
navigator.mediaDevices.getDisplayMedia
这个获取视频流的API来举例)。并通过pc.addTrack
方法将视频流添加到RTCPeerConnection中。 - 生成offer并设置为本地SDP(
pc.setLocalDescription
)并且将offer通过信令服务器发送给对方。 - 注册事件,比如:ice候选更新后需要发送给对方,收到对方的流需要处理,创建或者监听dataChannel等等。
- 作为接收方首先连接信令服务器,然后监听消息,一旦收到了对方的offe就应该创建RTCPeerConnection。
- 注册事件,比如:ice候选更新后需要发送给对方,收到对方的流需要处理,创建或者监听dataChannel等等。
- 将收到的offer设为pc的远程sdp(通过
pc.setRemoteDescription
)。 - 获取视频流并通过
pc.addTRack
方法将视频流添加到RTCPeerConnection中。 - 通过
pc.createAnswer
方法生成answer并将answer设置为本地sdp(pc.setLocalDescription
),然后将answer通过信令服务器发送给caller(发起者)。 - 最后,作为视频通话的发起方,需要监听被call方的发过来的sdp(answer),监听到后将answer设置为localDescription,这样连接就建立成功了。