概述
因为最近在做 WebRTC 相关的项目,为了对 WebRTC 建立连接和传输有更深入的了解,还是写一篇文章介绍一下。最开始是从 WebRTC 的官方文档入手,当然还有里面的 samples。因为通信的过程还没有涉及到,先从连接过程做切入。
SDP
SDP 是 Session Description Protocol,从文档里面可以看到,是 p2p 连接的标准协议,里面包括了 codec、地址和音视频的时间信息。这里面 SDP 不是通信协议,通信协议一般是 RTP 或者 SRTP(安全的 RTP),但是一般都会需要 SDP 来先进行连接建立。
Session description
session 是都过一行一个 field 的方式来描述的,格式是:
<character>=<value>
其中 <character> 是一个大小写敏感的字母,<value> 是一个结构化的字符串,通常是 utf- 8 编码的,等号后面不能直接跟空格。
SDP 消息里面有 3 个主要的块,session, timing 和 media描述。每个消息都包含了多个 timing 和media描述。每一行 field 顺序是固定的,*= 代表是可选的,每个含义如下:
**Session description**
v= (protocol version number, currently only 0)
o= (originator and session identifier : username, id, version number, network address)
s= (session name : mandatory with at least one UTF-8-encoded character)
i=\* (session title or short information)
u=\* (URI of description)
e=\* (zero or more email address with optional name of contacts)
p=\* (zero or more phone number with optional name of contacts)
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; see below)_
z=\* (time zone adjustments)
k=\* (encryption key)
a=\* (zero or more session attribute lines)
_Zero or more **Media descriptions** (each one starting by an "m=" line; see below)_
**Time description** (mandatory)
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 or information field)
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 — overriding the Session attribute lines)
一个常见的 SDP 消息是这样的:
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
RTCPeerConnection
所有连接都是从 RTCPeerConnection 这个对象开始,他继承自 EventTarget,拥有一些增加事件监听的能力。
Caller 打电话者(推流方 pc1)
- 创建 RTCPeerConnection 对象,以及准备需要推的 Stream 对象
pc1 = new RTCPeerConnection(servers);
localStream.getTracks().forEach((track) => {pc1.addTrack(track, localStream);
});
- 创建一个 Offer,并设置为自己的 LocalDescription
const offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
const offer = await pc1.createOffer(offerOptions);
pc1.setLocalDescription(offer);
- 拿到 pc2 的 Anwser,并设置为自己的 RemoteDescription
pc1.setRemoteDescription(answer);
Callee 接电话者(播放方 pc2)
- 拿到 pc1 的 Offer,设置为自己的 RemoteDescription
pc2.setLocalDescription(desc);
- 创建一个 Anwser,设置为自己的 LocalDescription
const answer =pc2.createAnswer();
pc2.setLocalDescription(answer);