WebRTC的全称为Web Real-Time Communication,跨平台支持P2P的音视频通信和任意数据的实时传输。适用于视频会议、在线教育、实时聊天、多人游戏和远程协作等场景。

WebRTC的核心组件

getUserMedia:捕获用户的音视频流

主要是调用前端设备的摄像头和麦克风,获取音视频流。可以使用navigator.mediaDevices.getUserMedia()方法来实现。F12打开控制台,输入以下代码,会弹出一个窗口,询问是否允许访问摄像头和麦克风。

navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
}).then(stream => {
  // 使用获取到的音视频流
}).catch(error => {
  console.error('Error accessing media devices.', error);
});

前端代码获取到的音视频流是一个MediaStream对象,可以通过video标签来播放。也可以通过网络传输到其他设备。

RTCPeerConnection:建立点对点连接

建立连接之前,双方需要交换SDP(Session Description Protocol)信息。SDP描述了音视频流的编码格式、分辨率、帧率等信息。

WebRTC采用P2P方式进行音视频通信,RTCPeerConnection是一个API,用于建立和管理点对点连接。可以通过RTCPeerConnection对象来设置ICE候选者和SDP(Session Description Protocol)信息,也可以通过它创建、保持、监控、关闭连接。

首先,音视频的发起方,需要创建一个RTCPeerConnection对象,并添加音视频流,然后创建一个offer,设置本地SDP,并发送给远端。

const peerConnection = new RTCPeerConnection();
// 添加音视频流
peerConnection.addStream(stream);
// 创建offer
peerConnection.createOffer().then(offer => {
  // 设置本地SDP
  return peerConnection.setLocalDescription(offer);
}).then(() => {
  // 发送offer给远端
}).catch(error => {
  console.error('Error creating offer.', error);
});

远端的接收方,保持监听状态,等待接收offer。接收到offer后,设置远端SDP,然后创建answer,设置本地SDP,并发送给发起方。

peerConnection.setRemoteDescription(new RTCSessionDescription(remoteSDP)).then(() => {
  // 创建answer
  return peerConnection.createAnswer();
}).then(answer => {
  // 设置本地SDP
  return peerConnection.setLocalDescription(answer);
}).then(() => {
  // 发送answer给远端
}).catch(error => {
  console.error('Error creating answer.', error);
});

此时,双方都已经设置了本地和对方的SDP信息,完成了媒体协商,这个过程一般通过信令服务器来完成。也就是双方都不知道对方的IP地址和端口号,只有信令服务器知道。接下来,双方需要建立点对点的连接,那么首先就得知道对方的IP地址和端口号。这个过程是通过ICE(Interactive Connectivity Establishment)来完成的。

ICE:实现内网穿透

ICE最重要的是实现内网穿透。候选人表示一个可能的连接地址,ICE会尝试多种方法来获取可用的IP地址和端口。ICE会在连接建立之前,收集候选者,并通过信令服务器交换候选者信息,最后来选择最佳的连接地址。ICE候选者有三类,按优先级从高到低排序:

  • Host候选者:本地网络接口的IP地址和端口号,通常是内网IP地址和端口号。
  • SRFLX候选者:通过STUN服务器获取的公网IP地址和端口号,通常是外网IP地址和NAT后的外网端口号。
  • Relay候选者:中继服务器的IP地址和端口号,通常是TURN服务器的IP地址和端口号。

ICE用于帮助通信双方在复杂的网络环境中建立连接。主要目标是实现NAT穿透,如果只是局域网通信,可以直接使用Host候选者。关键是要能够找到可用于WebRTC连接的IP地址和端口号,在NAT的环境下,需要用到STUN和TURN服务器,进行辅助的网络穿透。

STUN/TURN:辅助网络穿透

STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)是WebRTC中用于NAT穿透的两种协议。STUN服务器用于获取公网IP地址和端口号,TURN服务器用于中继数据流。

在理解STUN和TURN之前,先了解一下NAT,NAT映射私有IP地址到公网IP地址,可能是稳定的,也可能是动态的。如果它是稳定的,我们可以获取到某个私有地址和端口号对应的公网地址和端口号。如果这个端口号不稳定的话,我们只能通过中继服务器来传输数据。

STUN服务:

客户端向STUN服务器发送一个请求,STUN服务器会返回一个响应,响应中包含了客户端的公网IP地址和端口号。如果这个NAT是稳定的映射,那么我们可以直接使用这个公网IP地址和端口号进行通信。网上有公共的STUN服务器可以使用。WebRTC通信双方通过STUN服务器获取到自己的公网IP地址和端口号,然后通过信令服务器把这个信息发送给对方。这样就可以建立点对点的连接了。

TURN服务:

如果无法通过STUN获取稳定的公网IP和端口,那么我们就不能直接使用公网IP地址和端口号进行通信了。这个时候就需要使用TURN服务器。TURN服务器会充当中继服务器,把数据从一个客户端转发到另一个客户端。

WebRTC双方通过TRUN服务器中继通信的流程为:

  1. 客户端向TURN服务器发送请求,获取公网IP地址和端口号,称为中继地址。并且TURN服务器会和客户端建立一个长连接,以便于后续的数据传输。
  2. 客户端通过信令服务器把这个公网IP地址和端口号,即ICE候选人发送给对方。
  3. 对端客户端向TURN服务器发送请求,获取公网IP地址和端口号。
  4. 对端客户端通过信令服务器把这个公网IP地址和端口号发送给发起方。
  5. 对端客户端通过TURN服务器进行通信。
  6. TURN服务器会把某个中继地址收到的数据包,转发给对应的客户端。

总结

WebRTC可以通过简单API,实现音视频通信和数据传输。通信双方通过信令服务器交换SDP和ICE候选者信息,建立点对点连接。ICE用于实现内网穿透,STUN和TURN用于辅助网络穿透。WebRTC的核心组件包括getUserMediaRTCPeerConnectionICESTUNTURN。 WebRTC的应用场景包括视频会议、在线教育、实时聊天、多人游戏和远程协作等。WebRTC的优势在于跨平台支持P2P的音视频通信和任意数据的实时传输。