WebRTC端对端连接
RTCPeerConnection
一个核心类,是上层的统一接口。
在底层有很多复杂逻辑,媒体协商 、流轨道处理、数据接收发送、数据统计等等。
let pc = new RTCPeerConnection([config]);
参数
let config = {
// 传入多个ice server 就是多个stun/turn服务,获取到反射地址和中继地址
iceServers: [{
// 数组中每个元素都是RTCIceServer
// 凭证类型 password | oahth
credentialType: "password",
// 凭据,根据上面的type有不同的表示
credential: "",
// 用于连接服务中的url数组
urls: [""],
// 用户名,和credential配合
username: "mao"
}],
// 传输策略
// relay : 只收集中继后选择
// all : 收集所有类型的候选者
iceTransportPolicy: "all",
// banlance : 音频轨和视频轨使用自己的传输通道
// max-compat : 每个轨都用自己的传输通道
// max-bundle : 所有轨使用同一个传输通道
bundlePolicy: "balanced",
// 在收集candidate时使用
// 在收集rtcp和rtp复用的候选者
// negotiate : 如果能复用则复用,否则单独使用
// require : 能复用则复用,否则失败
rtcpMuxPolicy: "require",
peerIdentity: "",
// 授权可以使用的一组证书,不提供则会自动产生
certificates: [],
// icecandidate个数,如果个数超过了,则多出来的抛弃
// 如果数值被改变了,则会重新收集候选者
iceCandidatePoolSize: 3
};
方法
addIceCandidate
添加一个候选者信息
基本使用
let promi = pc.addIceCandidate(candi);
参数
let candi = {
// 描述信息
candidate: "",
// 流的类型,视频流还是音频流
sdpMid: 0,
// sdp 中 m= 的索引值
sdpMLineIndex: 10,
// 远端的唯一标志 ice-ufrag
usernameFragment: "qwer"
};
createOffer
创建offer
基本使用
let promi = pc.createOffer([config]);
参数
let config = {
// 会重新启动ice,重新收集cadidate
// 网络切换的时候,传输通道发生变化
// 如果当前使用的传输通道较为拥挤,可重新选
// 增加了新的中继节点,也需要重启ice
iceRestart: false,
// 静音检测
// 没有人声的时候,选择不传输背景噪音
// 减少带宽
voiceActivityDetection: true,
// 可接受音频
offerToReceiveAudio: 1,
// 可接受视频
offerToReceiveVideo: 1
};
协商过程
主要方法
方法 | 说明 | 使用 |
---|---|---|
createOffer | 创建本地的媒体sdp信息 | promise = pc.createOffer([config]); |
setLocalDescription | 设置本地媒体sdp描述信息 | pc.setLocalDescription(sdp); |
createAnswer | 对端收到offer后,要创建answer | pc.createAnswer([config]); |
setRemoteDescription | 收到对端的描述信息时设置 | pc.setRemoteDescription(sdp); |
addTrack | 添加一个轨 | sender = pc.addTrack(track, stream); |
removeTrack | 移除添加的轨 | pc.removeTrack(sender); |
重要事件
事件名 | 说明 |
---|---|
ontrack | 接收到了远程媒体数据 |
onnegotiationneeded | 进行媒体协商的时候触发 |
onicecandidate | 发现一个ice candidate的时候触发 |
端到端连接过程
SDP
Session Description Protocol
,可以被其它传输协议用于交换关键信息
格式为key=value
组成
包括:
- 元描述
- 网络描述
- 媒体流描述
- 安全描述
- 服务质量描述
# sdp版本,一般就是0
v=0
# owner session_name session_id version net_type address_type address>
o=- 1891166434071642414 2 IN IP4 127.0.0.1
# 会话名,如果不写则是-
s=-
# 存活时间
# 起始时间 结束时间,都是0表示不限制
t=0 0
# 设置全局属性
# 这一组媒体流绑定到一起,底层复用传输通道
a=group:BUNDLE 0 1 2
# media_stream_id : webrtc media stream
a=msid-semantic: WMS RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK
# 媒体层
# 媒体音频相关信息
# 包括使用的协议UDP/TLS/RTP/SAVPF 加密后的rtp
# 剩下一堆数字是payload type,表示媒体支持哪些类型
# 后面的a都是对这个的进一步说明
# media announcements
# media, port, tansport, payload type list
# 9 : 不接受数据
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
# webrtc 没使用
c=IN IP4 0.0.0.0
# a=type或者a=type:values
a=rtcp:9 IN IP4 0.0.0.0
# 用户名片段
a=ice-ufrag:wXYk
# 和上面组合使用
# 进行连通性检测时,检验有效性
# 如果验证通过了,则才能正常连接
# 保证链路的安全性
a=ice-pwd:SPCK9PpVHFt0P/dw7esp3eT9
# trickle 先不收集cadidate,在setLocalxxx的时候开始收集,每收集一个就开始检验
a=ice-options:trickle
# 指纹用于数据加密时,验证证书
a=fingerprint:sha-256 36:CB:81:6D:1C:AF:5B:78:D5:DD:D0:1E:BA:42:B8:1F:6B:4A:89:30:93:1F:CF:57:09:C7:0C:E4:9E:E7:7B:87
# 媒体协商时,作为服务端还是客户端 actpass/active/inactive
a=setup:actpass
# media_id 0 和上面的 bundle对应
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
# 这一端既可以发送也可接收
a=sendrecv
# media string id
a=msid:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK 53970061-890c-467e-8f61-bbf53a046e09
# rtcp rtp 端口复用
a=rtcp-mux
# rtpmap
# 修饰payload type 设置不同的参数
# a=rtpmap:payload_type encoding_name/采样率/声道数
a=rtpmap:111 opus/48000/2
# 媒体信息反馈
a=rtcp-fb:111 transport-cc
# fmtp 做进一步的说明
# a:fmtp:payload_type params
# apt 表示与 111 进行关联
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:3038924438 cname:xlEK51Hg6Owsod2z
a=ssrc:3038924438 msid:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK 53970061-890c-467e-8f61-bbf53a046e09
a=ssrc:3038924438 mslabel:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK
a=ssrc:3038924438 label:53970061-890c-467e-8f61-bbf53a046e09
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123 119 114 115 116
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:wXYk
a=ice-pwd:SPCK9PpVHFt0P/dw7esp3eT9
a=ice-options:trickle
a=fingerprint:sha-256 36:CB:81:6D:1C:AF:5B:78:D5:DD:D0:1E:BA:42:B8:1F:6B:4A:89:30:93:1F:CF:57:09:C7:0C:E4:9E:E7:7B:87
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK bd843891-9cfe-44c8-a546-8ce55f2b33ea
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
# 接收端带宽评估
a=rtcp-fb:96 goog-remb
# 传输端的带宽评估
a=rtcp-fb:96 transport-cc
# 编码控制回馈消息
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
# 99代表重传
a=rtpmap:99 rtx/90000
# 99是98的关联关联的通道,当98有数据丢失时,要重传的payload type 是97
a=fmtp:99 apt=98
a=rtpmap:100 VP9/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:122 rtx/90000
a=fmtp:122 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:124 H264/90000
a=rtcp-fb:124 goog-remb
a=rtcp-fb:124 transport-cc
a=rtcp-fb:124 ccm fir
a=rtcp-fb:124 nack
a=rtcp-fb:124 nack pli
a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=124
a=rtpmap:123 H264/90000
a=rtcp-fb:123 goog-remb
a=rtcp-fb:123 transport-cc
a=rtcp-fb:123 ccm fir
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtpmap:119 rtx/90000
a=fmtp:119 apt=123
# 允许冗余包
a=rtpmap:114 red/90000
a=rtpmap:115 rtx/90000
a=fmtp:115 apt=114
a=rtpmap:116 ulpfec/90000
a=ssrc-group:FID 1905224383 2910063675
a=ssrc:1905224383 cname:xlEK51Hg6Owsod2z
a=ssrc:1905224383 msid:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK bd843891-9cfe-44c8-a546-8ce55f2b33ea
a=ssrc:1905224383 mslabel:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK
a=ssrc:1905224383 label:bd843891-9cfe-44c8-a546-8ce55f2b33ea
a=ssrc:2910063675 cname:xlEK51Hg6Owsod2z
a=ssrc:2910063675 msid:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK bd843891-9cfe-44c8-a546-8ce55f2b33ea
a=ssrc:2910063675 mslabel:RwcoZ3RLzYRD2A6Q79I4wqUIqOVZ2XjmlApK
a=ssrc:2910063675 label:bd843891-9cfe-44c8-a546-8ce55f2b33ea
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:wXYk
a=ice-pwd:SPCK9PpVHFt0P/dw7esp3eT9
a=ice-options:trickle
a=fingerprint:sha-256 36:CB:81:6D:1C:AF:5B:78:D5:DD:D0:1E:BA:42:B8:1F:6B:4A:89:30:93:1F:CF:57:09:C7:0C:E4:9E:E7:7B:87
a=setup:actpass
a=mid:2
a=sctp-port:5000
a=max-message-size:262144