This repository has been archived by the owner on Aug 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
index.html
287 lines (249 loc) · 13.2 KB
/
index.html
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Dolby.io Getting Started with Video Calls</title>
<link rel="shortcut icon" href="https://go.dolby.io/hubfs/Dolby_April2021/images/favicon-32x32.png">
<!-- Bootstrap Bundle -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
<!-- Dolby.io Web SDK -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@voxeet/voxeet-web-sdk/dist/voxeet-sdk.js"></script>
<script type="text/javascript" src="https://developer.dolby.io/demos/comms-sdk-web-getting-started/util/dolbyio-auth-helper.js"></script>
</head>
<body>
<div class="container bg-dark text-white gx-4 px-4 py-4 mt-3 rounded">
<img src="https://go.dolby.io/hubfs/raw_assets/public/Dolby_April2021/images/dolby-io-logo.svg"/>
<h1>Getting Started with Video Calls</h1>
</div>
<div class="container px-4 mt-4">
<div class="row justify-content-around mt-3">
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<h2>Self-View</h2>
<style>
#self-view video { /* Flip the display of the local user in self view */
-webkit-transform: rotateY(180deg); /* Safari, Chrome */
-moz-transform: rotateY(180deg); /* Firefox */
transform: rotateY(180deg); /* Microsoft, etc. */
}
</style>
<div id="self-view"> <!-- Container for the local participant media stream -->
<p id="self-view-username"></p>
<i class="display-1 bi bi-person-video position-relative"></i>
</div>
<button type="button" class="btn btn-dark" id="btn-join">Join</button>
<button type="button" class="btn btn-dark" id="btn-leave">Leave</button>
</div>
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<h2>Remote-View</h2>
<div id="remote-view"> <!-- Container for the remote participant media stream -->
<p id="remote-view-username"></p>
<i class="display-1 bi bi-person-video position-relative"></i>
</div>
<button type="button" class="btn btn-dark" id="btn-invite"><i class="bi bi-clipboard2-plus-fill"></i> Invite</button>
</div>
</div>
</div>
<div class="container px-4 py-4 mt-3">
<p id="message"></p>
<p><a href="https://docs.dolby.io/communications-apis/docs/getting-started-with-the-javascript-sdk">Explore More Tutorials</a></p>
</div>
<!-- Prompt user for token and alias if not provided in URL -->
<div class="modal fade" id="token-prompt" tabindex="-1" aria-labelledby="token-prompt-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="token-prompt-label">Dolby.io Dashboard</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<label for="input-token" class="form-label">Demo Client Access Token:</label>
<input id="input-token" type="text" class="form-control">
</div>
<div class="modal-footer">
<button type="button" id="btn-token" class="btn btn-primary">Authenticate</button>
</div>
</div>
</div>
</div>
<!-- Bootstrap Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- Dolby.io Starter Application -->
<script type="text/javascript">
const shareMessage = (message) => {
document.getElementById("message").innerText = message;
}
/**
* Start by initializing the Web SDK with an access token. This starter project
* utilizes a helper function to pull the token from the query parameters in the URL.
*/
const initializeToken = () => {
console.group("Step 1: Initialize the SDK");
const token = dolbyio.getAccessToken();
VoxeetSDK.initializeToken(token, () => { console.log("Get a New Access Token"); });
shareMessage("Step 1: Web SDK initialized.");
console.groupEnd();
return token;
}
/**
* Start a session by establishing a communication link between this client application
* and the Dolby.io Platform. You need to provide the client name when establishing
* a new session, often this is the name that will be used by the participant.
*/
const openSession = async (sessionName) => {
console.group("Step 2: Open a Session");
console.log(`Session Name: ${sessionName}`);
try {
await VoxeetSDK.session.open({ name: sessionName });
shareMessage("Step 2: Session opened.");
} catch (error) {
console.error(error);
shareMessage(`Error opening session: ${error}`);
}
console.groupEnd();
}
/**
* Bi-directional communications for multiple participants occurs in a conference. Initially,
* the conference must be created before it can be joined. The conference should be given a
* unique and meaningful alias to help identify it among multiple conferences in an account.
*
* This should be in response to a user event so that they may approve media access to the
* microphone and camera.
*/
const createAndJoinConference = async (conferenceAlias, participantName) => {
if (!VoxeetSDK.session.isOpen()) { await openSession(participantName); };
console.group("Step 3: Create and Join a Conference");
console.log(`Conference Alias: ${conferenceAlias}`);
const joinOptions = {
constraints: { audio: true, video: true }
};
const conferenceOptions = {
alias: conferenceAlias
}
try {
const conference = await VoxeetSDK.conference.create(conferenceOptions);
await VoxeetSDK.conference.join(conference, joinOptions);
shareMessage(`Step 3: Conference '${conferenceAlias}' created and joined.`)
} catch (error) {
console.error(error);
}
console.groupEnd();
};
/**
* The SDK will trigger server-generated events which we can respond to
* for intended functionality.
*/
const handleConferenceFlow = () => {
// Custom behavior for when there is a media stream added
VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
console.log(`Stream Added for ${participant.info.name}`);
console.log(` Type: ${stream.type}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);
if (stream.type === "Camera") {
shareVideo(participant, stream);
}
});
// Custom behavior for when there is a media stream updated which happens once an attendee starts sharing video
VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
console.log(`Stream Updated for ${participant.info.name}`);
console.log(` Type: ${stream.type}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);
if (stream.type === "Camera" && stream.getVideoTracks().length) {
shareVideo(participant, stream);
}
});
// Custom behavior for when the app stops receiving a media stream for remote participants
VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
console.log(`Stream Removed for ${participant.info.name}`);
const videoNode = document.getElementById(`video-${participant.id}`);
if (videoNode) {
videoNode.parentNode.removeChild(videoNode);
}
});
// Custom behavior for when the participant has left the conference
VoxeetSDK.conference.on("left", async () => {
await VoxeetSDK.session.close();
console.log("Session closed.");
});
}
/**
* When a new participant camera media stream is detected, we determine which
* part of the user interface to update and create a video element that will
* display the incoming stream.
*/
const shareVideo = (participant, stream) => {
console.group("Step 4: Start and Share Video");
let perspective = "self-view";
if (VoxeetSDK.session.participant.id !== participant.id) {
console.log("Adding media stream for remote user.");
perspective = "remote-view";
}
let videoNode = document.getElementById(`video-${participant.id}`);
if (videoNode) {
console.log("Video node already created");
} else {
console.log(`Creating a video node: video-${participant.id}`);
videoNode = document.createElement("video");
videoNode.setAttribute("id", `video-${participant.id}`);
videoNode.setAttribute("height", "100%");
videoNode.setAttribute("width", "100%");
videoNode.muted = true; // Don't echo local audio
videoNode.autoplay = true; // Start right away
videoNode.playsinline = true; // Not full screen
const videoContainer = document.getElementById(perspective);
videoContainer.lastElementChild.replaceWith(videoNode);
videoContainer.firstElementChild.innerText = participant.info.name;
}
navigator.attachMediaStream(videoNode, stream);
shareMessage(`Step 4: Video of participant '${participant.info.name}' started.`);
console.groupEnd();
}
/**
* When the user decides to leave the conference you should stop sending the audio/video
* stream.
*/
const leaveConference = async () => {
console.group("Final Step: Leave the Conference");
try {
await VoxeetSDK.conference.leave();
shareMessage("Getting Started Success: Conference has ended.")
} catch (error) {
console.error(error);
}
console.groupEnd();
}
const main = async () => {
// Configure the application from query parameter values
const queryParams = new URLSearchParams(window.location.search);
const name = queryParams.get("name") || "developer";
const alias = queryParams.get("alias") || "web-sdk-starter";
// Establish Real-time Communications by first initializing the Dolby.io Web SDK with credentials
const token = await initializeToken();
// Start a new session and connect to the Dolby.io platform establishing a client-server link
await openSession(name);
// When user clicks the Join button, start and join a conference for the given alias
document.getElementById("btn-join").onclick = async () => {
await createAndJoinConference(alias, name);
};
// Define custom behavior for activity that occurs during a video call
handleConferenceFlow();
// When user clicks the Invite button, generate a url to join the same conference
document.getElementById("btn-invite").onclick = () => {
console.group("Step 5: Invite a remote participant")
let url = `https://developer.dolby.io/demos/comms-sdk-web-getting-started/index.html?token=${token}&alias=${alias}&name=guest`;
console.log(`Invite a guest with URL: ${url}`);
shareMessage(`Share the URL copied to your browser clipboard: ${url}`);
navigator.clipboard.writeText(url);
console.groupEnd();
}
// When user clicks the Leave button, end the conference
document.getElementById("btn-leave").onclick = async () => {
await leaveConference();
console.log("Getting Started Guide complete, congratulations!");
};
};
main();
</script>
</body>
</html>