WebRTC核心组件详解

1,897 阅读7分钟

RTCPeerConnection(点对点连接)

功能

建立两个客户端之间的音视频连接,包括网络协商(NAT穿越)、带宽管理、编解码、传输控制等。

应用场景

通过 P2P 连接,减少服务器压力,提高通信效率,如实时视频通话或多人会议。

使用

const peerConnection = new RTCPeerConnection();

RTCDataChannel(数据通道)

功能

WebRTC 支持在 P2P 连接中传输任意类型的二进制数据。通过数据通道,可以在两端传输文件、文本、甚至是游戏数据。

应用场景

用于点对点的文件传输,或者实时同步游戏状态、聊天消息等。

使用

const peerConnection = new RTCPeerConnection();

// 创建数据通道
const dataChannel = peerConnection.createDataChannel('chat');

// 监听数据通道的打开事件
dataChannel.onopen = () => {};

// 监听消息
dataChannel.onmessage = () => {};

ICE(交互式连接建立)

功能

ICE(Interactive Connectivity Establishment)协议用于 WebRTC 的 NAT 穿越和网络协商,通过收集候选的网络连接路径来建立对等连接。

应用场景

在两个客户端处于不同的网络环境时,ICE 通过候选路径的筛选找到可用的连接,确保通话的顺利建立。

使用

const peerConnection = new RTCPeerConnection();

// oniceandidate事件会在每找到一个新的候选地址时触发
peerConnection.oniceandidate = (event) => {
    // 通过信令服务器发送给远端也就是B端(如 WebSocket、HTTP 等)
    ws.send(JSON.stringify({ type: 'candidate', candidate: event.candidate });
};

// 监听ws消息
ws.onmessage = (message) => {
    const data = JSON.parse(message.data);
    // 收到ice消息之后将其设置为RTCPeerConnection的一部分,允许双方使用这个地址进行连接。
    if (data.type === 'candidate') {
        peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
    }
};

上述代码并没有做出A端和B端的区别,实际项目中可以使用一个用户唯一标识来区分A端和B端,比如用户的id,来达到双方交互ice候选者,我们可以做出以下修改:

const peerConnection = new RTCPeerConnection();
const currUserId = '当前登录用户的userId';

// oniceandidate事件会在每找到一个新的候选地址时触发
peerConnection.oniceandidate = (event) => {
    // 通过信令服务器(如 WebSocket、HTTP 等)发送给远端(与当前设备连接的另一端设备)
    ws.send(JSON.stringify({ 
        type: 'candidate', 
        candidate: event.candidate,
        target: 'target userId'
    });
};

// 监听ws消息
ws.onmessage = (message) => {
    const data = JSON.parse(message.data);
    // 收到ice消息之后将其设置为RTCPeerConnection的一部分,允许双方使用这个地址进行连接。
    if (data.type === 'candidate' && data.target !== currUserId) {
        peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
    }
};

SDP(会话描述协议)

功能

SDP(Session Description Protocol)用于描述多媒体会话的参数,WebRTC 通过 SDP 交换对等节点的音视频格式、编解码器等参数,完成协商过程。

应用场景

用于两个客户端之间协商音视频格式、编解码器等,确保双方能够理解彼此的数据格式。

offer和answer

offer

在 WebRTC 中,offer 是用于建立点对点连接的重要步骤之一。它包含了发起端点所支持的会话信息,比如音视频流的格式、编码解码器、网络连接的候选路径(ICE candidate)等。具体来说,offer 的作用是让对方了解当前端点希望如何进行通信。

offer的作用
  1. 协商通信参数

    • Offer 是由 WebRTC 中的 RTCPeerConnection 对象创建的一个会话描述(SDP,Session Description Protocol),它描述了发起端的媒体能力和期望的通信参数。
    • 其中包括了音视频流的媒体格式(如视频的分辨率、帧率、音频采样率等)、编码方式(如 H.264、VP8 等编解码器)、网络协商信息等。
    • 通过 offer,发起方告诉接收方自己能支持什么样的通信方式以及如何传输数据。
  2. 触发通信协商流程

    • Offer 是 WebRTC 连接的发起方所发送的“邀请”,它标志着点对点连接协商的开始。接收方接收到 offer 后,需要根据 offer 的信息创建一个 answer,并将其返回给发起方,以确认通信参数。
    • Answer 是对 offer 的响应,它会确认哪些编解码器和媒体流参数可以被双方支持。
  3. SDP (Session Description Protocol)

    • Offer 本质上是 SDP 数据,描述了媒体的相关信息。在创建 offer 时,WebRTC 会为发起方生成一个包含媒体流详细描述的 SDP。接收方可以通过解析这个 SDP,了解发起方支持的编码、解码器和其他网络参数,从而决定是否接受这个通信配置。

answer

在 WebRTC 中,answer 是连接协商过程中由被邀请方生成并发送给发起方的回应描述,它是整个连接协商的关键步骤之一。它用于回应发起方发送的 offer,并且通过描述被邀请方的媒体能力和网络配置来完成双方的连接协商。

answer的作用
  1. 回应 offer: 当一个对等方发起连接时,它首先生成一个 offer,描述了它可以支持的媒体参数(如音频、视频编码格式等)。接收到 offer 的对等方需要生成一个 answer,它是一份对 offer 的回应,描述被邀请方支持的媒体能力。
  2. 完成连接协商answer 会包含对等方所接受的媒体格式和连接信息(如音视频编解码器、网络地址、带宽等),发起方收到 answer 后,将其设置为远端描述,最终完成连接的协商。此时,双方都了解如何传输媒体流,并可以开始音视频通信。
  3. 确保双方兼容answer 通过 SDP(Session Description Protocol) 来描述被邀请方的能力,与 offer 一起,确保双方的媒体流传输方式、编码格式、带宽等参数兼容,以便能够顺利建立 P2P 连接。
WebRTC offer和answer交互的基本流程
  1. 创建 offer(通常由 A 端发起):

    • 发起连接的一端(A 端)创建一个 offer(通过 createOffer()),它包含了发起方的媒体能力和连接信息。
    • A 端通过信令服务器将 offer 发送给 B 端。
  2. 设置本地描述

    • A 端调用 setLocalDescription(offer),将这个 offer 作为自己的本地描述(local description)。
  3. 设置远端描述(在 B 端):

    • B 端收到 A 端的 offer 后,调用 setRemoteDescription(offer),将 A 端的 offer 作为远端描述(remote description)。
    • 这一步让 B 端知道 A 端期望的媒体类型、网络设置等,并使 B 端能够基于此进行响应。
  4. 创建 answer(由 B 端回应):

    • B 端基于 A 端的 offer 创建一个 answer(通过 createAnswer()),并将其发送给 A 端。
  5. 双方互换描述

    • A 端接收 B 端的 answer,并调用 setRemoteDescription(answer) 来将 B 端的描述设置为远端描述。
    • B 端也通过 setLocalDescription(answer) 设置自己的本地描述。
API
  • RTCSessionDescription: 是 WebRTC 中表示会话描述的一个接口。它封装了会话的 SDP 数据,并指定该描述的类型(offeranswer)。每个对等端(Peer)在发起或响应连接时会用到这个类来封装和解析 SDP。
  • createOffer(): 用于发起会话,并生成一个 SDP offer,包含本地媒体能力和 ICE 候选信息。通常由发起端(Peer A)调用。
  • createOffer(): 用于响应收到的 offer,并生成一个 SDP answer。它通常由被邀请端(Peer B)调用。
  • setLocalDescription(): 用来设置远端会话描述。通常用来接收远端发送过来的 SDP offerSDP answer。通过该方法,浏览器可以根据远端提供的媒体和连接参数来建立连接。
  • setRemoteDescription(): 用来设置远端会话描述。通常用来接收远端发送过来的 SDP offerSDP answer。通过该方法,浏览器可以根据远端提供的媒体和连接参数来建立连接(简单来说就是告诉本地端对方的连接细节,以便本地端可以做出相应的准备和设置。)
  • localDescription: 表示本地端的SDP描述。
  • remoteDescription: 表示远端的SDP描述。
示例
const peerConnection = new RTCPeerConnection();

// 创建一个offer
peerConnection.createOffer()
    .then(offer => peerConnection.setLocalDescription(offer)
    .then(offer => {
        // 通过信令服务器发送给远端
        ws.send(JSON.stringify({ type: 'offer', offer: peerConnection.localDescription }))
    })

// 监听消息: 处理SDP
ws.onmessage = (message) {
    const data = JSON.parse(message);
    if (data.type === 'offer') {
      peerConnection.setRemoteDescription(new RTCSessionDescription(data.offer))
          .then(() => peerConnection.createAnswer())
          .then((answer) => peerConnection.setLocalDescription(answer))
          .then(() => {
              ws.send(JSON.stringify({ type: 'answer', answer: peerConnection.localDescription }));
          });
    } else if (data.type === 'answer') {
        peerConnection.setRemoteDescription(new RTCSessionDescription(data.answer));
    }
};