-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
250 lines (208 loc) · 6.45 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
import './style.css';
import firebase from 'firebase/app';
import 'firebase/firestore';
const firebaseConfig =
{
apiKey: "AIzaSyBjgasE-mpCCPapVU6csMDCxGA0bCDzuUw",
authDomain: "cs553-dcc51.firebaseapp.com",
projectId: "cs553-dcc51",
storageBucket: "cs553-dcc51.appspot.com",
messagingSenderId: "195541698192",
appId: "1:195541698192:web:7120b77c32e5c35e647a15",
measurementId: "G-C3LBY38X6K"
};
if (!firebase.apps.length)
{
firebase.initializeApp(firebaseConfig);
}
// Firestore object
const firestore = firebase.firestore();
// STUN servers used
const servers =
{
iceServers:
[
{
urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'],
},
],
iceCandidatePoolSize: 10,
};
// Set up peer connection and stream variables
const peerConnection = new RTCPeerConnection(servers);
let localStream = null;
let remoteStream = null;
// Get HTML objects
const webcamButton = document.getElementById('webcamButton');
const webcamVideo = document.getElementById('webcamVideo');
const videoButtonOn = document.getElementById('videoButtonOn');
const videoButtonOff = document.getElementById('videoButtonOff');
const audioButtonOn = document.getElementById('audioButtonOn');
const audioButtonOff = document.getElementById('audioButtonOff');
const callButton = document.getElementById('callButton');
const callInput = document.getElementById('callInput');
const callCode = document.getElementById('callCode');
const answerButton = document.getElementById('answerButton');
const remoteVideo = document.getElementById('remoteVideo');
const hangupButton = document.getElementById('hangupButton');
// Initial setup for video and microphone resources
webcamButton.onclick = async () =>
{
localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
remoteStream = new MediaStream();
// console.log(localStream)
// Add local stream to peer connection
localStream.getTracks().forEach((track) =>
{
peerConnection.addTrack(track, localStream);
});
// Set video stream from remote stream
peerConnection.ontrack = (event) =>
{
event.streams[0].getTracks().forEach((track) =>
{
remoteStream.addTrack(track);
});
};
webcamVideo.srcObject = localStream;
remoteVideo.srcObject = remoteStream;
callButton.disabled = false;
answerButton.disabled = false;
videoButtonOff.disabled = false;
audioButtonOff.disabled = false;
callCode.disabled = false;
callInput.disabled = false;
webcamButton.disabled = true;
};
// Functionality to handle camera on/off and audio mute/unmute
videoButtonOn.onclick = async() =>
{
// localStream = await navigator.mediaDevices.getUserMedia({ video: true });
webcamVideo.srcObject = localStream;
videoButtonOff.disabled = false;
videoButtonOn.disabled = true;
}
videoButtonOff.onclick = async() =>
{
// localStream.getVideoTracks().forEach((track) =>
// {
// peerConnection.removeTrack(track);
// });
// localStream.muted = true;
webcamVideo.srcObject = null;
peerConnection.enabled = false;
// // Add local stream to peer connection
// localStream.getTracks().forEach((track) =>
// {
// peerConnection.removeTrack(track);
// });
// // Set video stream from remote stream
// peerConnection.ontrack = (event) =>
// {
// event.streams[0].getTracks().forEach((track) =>
// {
// remoteStream.addTrack(track);
// });
// };
videoButtonOn.disabled = false;
videoButtonOff.disabled = true;
}
audioButtonOn.onclick = async() =>
{
audioButtonOff.disabled = false;
audioButtonOn.disabled = true;
}
audioButtonOff.onclick = async() =>
{
audioButtonOn.disabled = false;
audioButtonOff.disabled = true;
}
// Creating an offer
callButton.onclick = async () =>
{
// Firestore collections used for facilitating signaling
const callDoc = firestore.collection('calls').doc();
const offerCandidates = callDoc.collection('offerCandidates');
const answerCandidates = callDoc.collection('answerCandidates');
callCode.value = callDoc.id;
// Save to database - candidates for call
peerConnection.onicecandidate = (event) =>
{
event.candidate && offerCandidates.add(event.candidate.toJSON());
};
// Creating offer for call
const offerDescription = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offerDescription);
const offer =
{
sdp: offerDescription.sdp,
type: offerDescription.type,
};
await callDoc.set({ offer });
// Listening for remote answer
callDoc.onSnapshot((snapshot) => {
const data = snapshot.data();
if (!peerConnection.currentRemoteDescription && data?.answer)
{
const answerDescription = new RTCSessionDescription(data.answer);
peerConnection.setRemoteDescription(answerDescription);
}
});
// Adding canditate to the connection when call is answered
answerCandidates.onSnapshot((snapshot) =>
{
snapshot.docChanges().forEach((change) =>
{
if (change.type === 'added')
{
const candidate = new RTCIceCandidate(change.doc.data());
peerConnection.addIceCandidate(candidate);
}
});
});
hangupButton.disabled = false;
};
// Answering calls
answerButton.onclick = async () =>
{
const callId = callInput.value;
const callDoc = firestore.collection('calls').doc(callId);
const answerCandidates = callDoc.collection('answerCandidates');
const offerCandidates = callDoc.collection('offerCandidates');
peerConnection.onicecandidate = (event) =>
{
event.candidate && answerCandidates.add(event.candidate.toJSON());
};
const callData = (await callDoc.get()).data();
const offerDescription = callData.offer;
await peerConnection.setRemoteDescription(new RTCSessionDescription(offerDescription));
const answerDescription = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answerDescription);
const answer =
{
type: answerDescription.type,
sdp: answerDescription.sdp,
};
await callDoc.update({ answer });
offerCandidates.onSnapshot((snapshot) =>
{
snapshot.docChanges().forEach((change) =>
{
console.log(change);
if (change.type === 'added')
{
let data = change.doc.data();
peerConnection.addIceCandidate(new RTCIceCandidate(data));
}
});
});
hangupButton.disabled = false;
};
// Hangup functionality
hangupButton.onclick = async () =>
{
// peerConnection.enabled = false;
peerConnection.close();
webcamVideo.srcObject = null;
remoteVideo.srcObject = null;
}