Skip to content

Commit 77e5695

Browse files
committed
add RTCPeerConnection
1 parent 98bec6d commit 77e5695

File tree

3 files changed

+240
-0
lines changed

3 files changed

+240
-0
lines changed

12.RTCPeerConnection/index.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<title>Document</title>
8+
<style>
9+
video {
10+
max-width: 100%;
11+
width: 320px;
12+
}
13+
</style>
14+
</head>
15+
<body>
16+
<video id='localVideo' autoplay playsinline></video>
17+
<video id='remoteVideo' autoplay playsinline></video>
18+
<div>
19+
<button id='startButton'>Start</button>
20+
<button id='callButton'>Call</button>
21+
<button id='hangupButton'>Hang Up</button>
22+
</div>
23+
<script src='../libs/adapter-latest.js'></script>
24+
<script src='./index.js'></script>
25+
</body>
26+
</html>

12.RTCPeerConnection/index.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
'use strict';
2+
3+
(function() {
4+
const mediaStreamConstraints = {
5+
video: true,
6+
};
7+
8+
const offerOptions = {
9+
offerToReceiveVideo: 1,
10+
};
11+
12+
const localVideo = document.getElementById('localVideo');
13+
const remoteVideo = document.getElementById('remoteVideo');
14+
const startButton = document.getElementById('startButton');
15+
const callButton = document.getElementById('callButton');
16+
const hangupButton = document.getElementById('hangupButton');
17+
18+
callButton.disabled = true;
19+
hangupButton.disabled = true;
20+
21+
startButton.addEventListener('click', startAction);
22+
callButton.addEventListener('click', callAction);
23+
hangupButton.addEventListener('click', hangupAction);
24+
25+
let localStream;
26+
let remoteStream;
27+
28+
let localPeerConnection;
29+
let remotePeerConnection;
30+
31+
function trace(text) {
32+
text = text.trim();
33+
const now = (window.performance.now() / 1000).toFixed(3);
34+
35+
console.log(now, text);
36+
}
37+
38+
function gotLocalMediaStream(mediaStream) {
39+
localVideo.srcObject = mediaStream;
40+
localStream = mediaStream;
41+
trace('Received local stream.');
42+
callButton.disabled = false;
43+
}
44+
45+
function gotRemoteMediaStream(event) {
46+
const mediaStream = event.stream;
47+
remoteVideo.srcObject = mediaStream;
48+
remoteStream = mediaStream;
49+
trace('Remote peer connection received remote stream.');
50+
}
51+
52+
function handleLocalMediaStreamError(error) {
53+
trace(`navigator.mediaDevices.getUserMedia error: ${error.toString()}.`);
54+
}
55+
56+
function handleConnection(event) {
57+
const peerConnection = event.target;
58+
const iceCandidate = event.candiate;
59+
60+
if (iceCandidate) {
61+
const newIceCandidate = new RTCIceCandidate(iceCandidate);
62+
const otherPeer = getOtherPeer(peerConnection);
63+
64+
otherPeer.addIceCandidate(newIceCandidate)
65+
.then(() => handleConnectionSuccess(peerConnection))
66+
.catch(error => handleConnectionFailure(peerConnection, error));
67+
68+
trace(`${getPeerName(peerConnection)} ICE candidate:\n${iceCandidate.candidate}.`);
69+
}
70+
}
71+
72+
function handleConnectionChange(event) {
73+
const peerConnection = event.target;
74+
console.log('ICE state change event: ', event);
75+
trace(`${getPeerName(peerConnection)} ICE state: ${peerConnection.iceConnectionState}.`);
76+
}
77+
78+
function handleConnectionSuccess(peerConnection) {
79+
trace(`${getPeerName(peerConnection)} addIceCandidate success.`);
80+
}
81+
82+
function handleConnectionFailure(peerConnection, error) {
83+
trace(`${getPeerName(peerConnection)} failed to add ICE Candidate:\n${error.toString()}.`);
84+
}
85+
86+
function createdOffer(description) {
87+
trace(`Offer from localPeerConnection:\n${description.sdp}`);
88+
89+
trace('localPeerConnection setLocalDescription start.');
90+
localPeerConnection.setLocalDescription(description)
91+
.then(() => setLocalDescriptionSuccess(localPeerConnection))
92+
.catch(setSessionDescriptionError);
93+
94+
trace('remotePeerConnection setRemoteDescription start.');
95+
remotePeerConnection.setRemoteDescription(description)
96+
.then(() => setRemoteDescriptionSuccess(remotePeerConnection))
97+
.catch(setSessionDescriptionError);
98+
99+
trace('remotePeerConnection createAnswer start.');
100+
remotePeerConnection.createAnswer()
101+
.then(createdAnswer)
102+
.catch(setSessionDescriptionError);
103+
}
104+
105+
function createdAnswer(description) {
106+
trace(`Answer from remotePeerConnection:\n${description.sdp}.`);
107+
108+
trace('remotePeerConnection setLocalDescription start.');
109+
remotePeerConnection.setLocalDescription(description)
110+
.then(() => setLocalDescriptionSuccess(remotePeerConnection))
111+
.catch(setSessionDescriptionError);
112+
113+
trace('localPeerConnection setRemoteDescription start.');
114+
localPeerConnection.setRemoteDescription(description)
115+
.then(() => setRemoteDescriptionSuccess(localPeerConnection))
116+
.catch(setSessionDescriptionError);
117+
}
118+
119+
function setDescriptionSuccess(peerConnection, functionName) {
120+
const peerName = getPeerName(peerConnection);
121+
trace(`${peerName} ${functionName} complete.`);
122+
}
123+
124+
function setLocalDescriptionSuccess(peerConnection) {
125+
setDescriptionSuccess(peerConnection, 'setLocalDescription');
126+
}
127+
128+
function setRemoteDescriptionSuccess(peerConnection) {
129+
setDescriptionSuccess(peerConnection, 'setRemoteDescription');
130+
}
131+
132+
function setSessionDescriptionError(error) {
133+
trace(`Failed to create session description: ${error.toString()}.`);
134+
}
135+
136+
function getOtherPeer(peerConnection) {
137+
return (peerConnection === localPeerConnection) ?
138+
remotePeerConnection : localPeerConnection;
139+
}
140+
141+
function getPeerName(peerConnection) {
142+
return (peerConnection === localPeerConnection) ?
143+
'localPeerConnection' : 'remotePeerConnection';
144+
}
145+
146+
function startAction(e) {
147+
startButton.disabled = true;
148+
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
149+
.then(gotLocalMediaStream)
150+
.catch(handleLocalMediaStreamError);
151+
trace('Requesting local stream.');
152+
}
153+
154+
function callAction(e) {
155+
callButton.disabled = true;
156+
hangupButton.disabled = false;
157+
158+
trace('Start calling.');
159+
160+
const videoTracks = localStream.getVideoTracks();
161+
const audioTracks = localStream.getAudioTracks();
162+
if (videoTracks.length > 0) {
163+
trace(`Using video device: ${videoTracks[0].label}.`);
164+
}
165+
if (audioTracks.length > 0) {
166+
trace(`Using audio device: ${audioTracks[0].label}.`);
167+
}
168+
169+
const servers = null;
170+
171+
localPeerConnection = new RTCPeerConnection(servers);
172+
trace('Created local peer connection object localPeerConnection.');
173+
174+
localPeerConnection.addEventListener('icecandidate', handleConnection);
175+
localPeerConnection.addEventListener(
176+
'iceconnectionstatechange', handleConnectionChange
177+
);
178+
179+
remotePeerConnection = new RTCPeerConnection(servers);
180+
trace('Created remote peer connection object remotePeerConnection.');
181+
182+
remotePeerConnection.addEventListener('icecandidate', handleConnection);
183+
remotePeerConnection.addEventListener(
184+
'iceconnectionstatechange', handleConnectionChange
185+
);
186+
remotePeerConnection.addEventListener('addstream', gotRemoteMediaStream);
187+
188+
localPeerConnection.addStream(localStream);
189+
trace('Added local stream to localPeerConnection.');
190+
191+
trace('localPeerConnection createOffer start.');
192+
localPeerConnection.createOffer(offerOptions)
193+
.then(createdOffer)
194+
.catch(setSessionDescriptionError);
195+
}
196+
197+
function hangupAction(e) {
198+
localPeerConnection.close();
199+
localPeerConnection = null;
200+
201+
remotePeerConnection.close();
202+
remotePeerConnection = null;
203+
204+
hangupButton.disabled = true;
205+
callButton.disabled = false;
206+
trace('Ending call.');
207+
}
208+
})();

index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
<li>
2424
<a href="./05.share_desktop/index.html">Share Desktop</a>
2525
</li>
26+
<li>
27+
<a href="./11.nodejs_signal/index.html">Signal</a>
28+
</li>
29+
<li>
30+
<a href="./12.RTCPeerConnection/index.html">RTCPeerConnection</a>
31+
</li>
2632
</ul>
2733
</body>
2834
</html>

0 commit comments

Comments
 (0)