跳到主要内容

7.3. Early Transport Warmup Example (早期传输预热示例)

本示例演示了第 4.1.10.1 节中描述的早期预热技术。在这里, Alice 的端点向 Bob 的端点发送一个 offer 以开始音频/视频呼叫。Bob 立即响应一个 answer, 该 answer 接受音频/视频 "m=" section 但将它们标记为 sendonly (从他的角度), 这意味着 Alice 还不会发送媒体。这允许 JSEP 实现立即开始协商 ICE 和 DTLS。然后 Bob 的端点提示他接听电话, 当他接听时, 他的端点发送第二个 offer, 该 offer 启用音频和视频 "m=" section, 从而实现双向媒体传输。这种流程的优点是, 一旦收到第一个 answer, 实现就可以继续进行 ICE 和 DTLS 协商并建立会话传输。如果传输设置在发送第二个 offer 之前完成, 那么被叫方可以在接听电话后立即传输媒体, 从而最小化感知的拨号后延迟。第二次 offer/answer 交换还可以更改首选编解码器或其他会话参数。

本示例还使用了第 3.5.3 节中描述的 "relay" ICE 候选策略, 以最小化所需的 ICE 收集和检查。

//                  set up local media state
AliceJS->AliceUA: create new PeerConnection with "relay" ICE policy
AliceJS->AliceUA: addTrack with two tracks: audio and video
AliceJS->AliceUA: createOffer to get |offer-C1|
AliceJS->AliceUA: setLocalDescription with |offer-C1|

// |offer-C1| is sent over signaling protocol to Bob
AliceJS->WebServer: signaling with |offer-C1|
WebServer->BobJS: signaling with |offer-C1|

// |offer-C1| arrives at Bob
BobJS->BobUA: create new PeerConnection with "relay" ICE policy
BobJS->BobUA: setRemoteDescription with |offer-C1|
BobUA->BobJS: ontrack events for audio and video

// a relay candidate is sent to Bob
AliceUA->AliceJS: onicecandidate (relay) |offer-C1-candidate-1|
AliceJS->WebServer: signaling with |offer-C1-candidate-1|

WebServer->BobJS: signaling with |offer-C1-candidate-1|
BobJS->BobUA: addIceCandidate with |offer-C1-candidate-1|

// Bob prepares an early answer to warm up the
// transport
BobJS->BobUA: addTransceiver with null audio and video tracks
BobJS->BobUA: transceiver.setDirection(sendonly) for both
BobJS->BobUA: createAnswer
BobJS->BobUA: setLocalDescription with answer

// |answer-C1| is sent over signaling protocol
// to Alice
BobJS->WebServer: signaling with |answer-C1|
WebServer->AliceJS: signaling with |answer-C1|

// |answer-C1| (sendonly) arrives at Alice
AliceJS->AliceUA: setRemoteDescription with |answer-C1|
AliceUA->AliceJS: ontrack events for audio and video

// a relay candidate is sent to Alice
BobUA->BobJS: onicecandidate (relay) |answer-B1-candidate-1|
BobJS->WebServer: signaling with |answer-B1-candidate-1|

WebServer->AliceJS: signaling with |answer-B1-candidate-1|
AliceJS->AliceUA: addIceCandidate with |answer-B1-candidate-1|

// ICE and DTLS establish while call is ringing

// Bob accepts call, starts media, and sends
// new offer
BobJS->BobUA: transceiver.setTrack with audio and video tracks
BobUA->AliceUA: media sent from Bob to Alice
BobJS->BobUA: transceiver.setDirection(sendrecv) for both
transceivers
BobJS->BobUA: createOffer
BobJS->BobUA: setLocalDescription with offer

// |offer-C2| is sent over signaling protocol
// to Alice
BobJS->WebServer: signaling with |offer-C2|
WebServer->AliceJS: signaling with |offer-C2|

// |offer-C2| (sendrecv) arrives at Alice
AliceJS->AliceUA: setRemoteDescription with |offer-C2|
AliceJS->AliceUA: createAnswer
AliceJS->AliceUA: setLocalDescription with |answer-C2|
AliceUA->BobUA: media sent from Alice to Bob

// |answer-C2| is sent over signaling protocol
// to Bob
AliceJS->WebServer: signaling with |answer-C2|
WebServer->BobJS: signaling with |answer-C2|
BobJS->BobUA: setRemoteDescription with |answer-C2|

|offer-C1| 的 SDP 如下:

v=0
o=- 1070771854436052752 1 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle ice2
a=group:BUNDLE a1 v1
a=group:LS a1 v1

m=audio 9 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 0.0.0.0
a=mid:a1
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=fmtp:97 0-15
a=fmtp:98 0-15
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:bbce3ba6-abfc-ac63-d00a-e15b286f8fce
a=ice-ufrag:4ZcD
a=ice-pwd:ZaaG6OG7tCn4J/lehAGz+HHD
a=fingerprint:sha-256
C4:68:F8:77:6A:44:F1:98:6D:7C:9F:47:EB:E3:34:A4:
0A:AA:2D:49:08:28:70:2E:1F:AE:18:7D:4E:3E:66:BF
a=setup:actpass
a=tls-id:9e5b948ade9c3d41de6617b68f769e55
a=rtcp-mux
a=rtcp-mux-only
a=rtcp-rsize

m=video 0 UDP/TLS/RTP/SAVPF 100 101 102 103
c=IN IP4 0.0.0.0
a=mid:v1
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 H264/90000
a=fmtp:101 packetization-mode=1;profile-level-id=42e01f
a=rtpmap:102 rtx/90000
a=fmtp:102 apt=100
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=101
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:bbce3ba6-abfc-ac63-d00a-e15b286f8fce
a=bundle-only

|offer-C1-candidate-1| 如下:

ufrag 4ZcD
index 0
mid a1
attr candidate:1 1 udp 255 192.0.2.100 12100 typ relay
raddr 0.0.0.0 rport 0

|answer-C1| 的 SDP 如下:

v=0
o=- 6386516489780559513 1 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle ice2
a=group:BUNDLE a1 v1
a=group:LS a1 v1

m=audio 9 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 0.0.0.0
a=mid:a1
a=sendonly
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=fmtp:97 0-15
a=fmtp:98 0-15
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:751f239e-4ae0-c549-aa3d-890de772998b
a=ice-ufrag:TpaA
a=ice-pwd:t2Ouhc67y8JcCaYZxUUTgKw/
a=fingerprint:sha-256
A2:F3:A5:6D:4C:8C:1E:B2:62:10:4A:F6:70:61:C4:FC:
3C:E0:01:D6:F3:24:80:74:DA:7C:3E:50:18:7B:CE:4D
a=setup:active
a=tls-id:55e967f86b7166ed14d3c9eda849b5e9
a=rtcp-mux
a=rtcp-mux-only
a=rtcp-rsize

m=video 9 UDP/TLS/RTP/SAVPF 100 101 102 103
c=IN IP4 0.0.0.0
a=mid:v1
a=sendonly
a=rtpmap:100 VP8/90000
a=rtpmap:101 H264/90000
a=fmtp:101 packetization-mode=1;profile-level-id=42e01f
a=rtpmap:102 rtx/90000
a=fmtp:102 apt=100
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=101
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:751f239e-4ae0-c549-aa3d-890de772998b

|answer-C1-candidate-1| 如下:

ufrag TpaA
index 0
mid a1
attr candidate:1 1 udp 255 192.0.2.200 12200 typ relay
raddr 0.0.0.0 rport 0

|offer-C2| 的 SDP 如下:

v=0
o=- 6386516489780559513 2 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle ice2
a=group:BUNDLE a1 v1
a=group:LS a1 v1

m=audio 12200 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 192.0.2.200
a=mid:a1
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=fmtp:97 0-15
a=fmtp:98 0-15
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:751f239e-4ae0-c549-aa3d-890de772998b
a=ice-ufrag:TpaA
a=ice-pwd:t2Ouhc67y8JcCaYZxUUTgKw/
a=fingerprint:sha-256
A2:F3:A5:6D:4C:8C:1E:B2:62:10:4A:F6:70:61:C4:FC:
3C:E0:01:D6:F3:24:80:74:DA:7C:3E:50:18:7B:CE:4D
a=setup:actpass
a=tls-id:55e967f86b7166ed14d3c9eda849b5e9
a=rtcp-mux
a=rtcp-mux-only
a=rtcp-rsize
a=candidate:1 1 udp 255 192.0.2.200 12200 typ relay
raddr 0.0.0.0 rport 0
a=end-of-candidates

m=video 12200 UDP/TLS/RTP/SAVPF 100 101 102 103
c=IN IP4 192.0.2.200
a=mid:v1
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 H264/90000
a=fmtp:101 packetization-mode=1;profile-level-id=42e01f
a=rtpmap:102 rtx/90000
a=fmtp:102 apt=100
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=101
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:751f239e-4ae0-c549-aa3d-890de772998b

|answer-C2| 的 SDP 如下:

v=0
o=- 1070771854436052752 2 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle ice2
a=group:BUNDLE a1 v1
a=group:LS a1 v1

m=audio 12100 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 192.0.2.100
a=mid:a1
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=fmtp:97 0-15
a=fmtp:98 0-15
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:bbce3ba6-abfc-ac63-d00a-e15b286f8fce
a=ice-ufrag:4ZcD
a=ice-pwd:ZaaG6OG7tCn4J/lehAGz+HHD
a=fingerprint:sha-256
C4:68:F8:77:6A:44:F1:98:6D:7C:9F:47:EB:E3:34:A4:
0A:AA:2D:49:08:28:70:2E:1F:AE:18:7D:4E:3E:66:BF
a=setup:passive
a=tls-id:9e5b948ade9c3d41de6617b68f769e55
a=rtcp-mux
a=rtcp-mux-only
a=rtcp-rsize
a=candidate:1 1 udp 255 192.0.2.100 12100 typ relay
raddr 0.0.0.0 rport 0
a=end-of-candidates

m=video 12100 UDP/TLS/RTP/SAVPF 100 101 102 103
c=IN IP4 192.0.2.100
a=mid:v1
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 H264/90000
a=fmtp:101 packetization-mode=1;profile-level-id=42e01f
a=rtpmap:102 rtx/90000
a=fmtp:102 apt=100
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=101
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:bbce3ba6-abfc-ac63-d00a-e15b286f8fce