index.html comms-getting-started

Created Diff never expires
48 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
287 lines
78 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
301 lines
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<html lang="en">
<head>
<head>
<meta charset="utf-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">


<title>Dolby.io Getting Started with Video Calls</title>
<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">
<link rel="shortcut icon" href="https://go.dolby.io/hubfs/Dolby_April2021/images/favicon-32x32.png">


<!-- Bootstrap Bundle -->
<!-- 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 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">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">


<!-- Dolby.io Web SDK -->
<!-- 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://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>
<script type="text/javascript" src="../util/dolbyio-auth-helper.js"></script>
<!-- Auth0 Single Page Application SDK -->
<script src="https://cdn.auth0.com/js/auth0-spa-js/1.2/auth0-spa-js.production.js"></script>
<script src="./app.js"></script>
</head>
</head>
<body>
<body>


<div class="container bg-dark text-white gx-4 px-4 py-4 mt-3 rounded">
<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"/>
<img src="https://go.dolby.io/hubfs/raw_assets/public/Dolby_April2021/images/dolby-io-logo.svg" />
<h1>Getting Started with Video Calls</h1>
<h1>Getting Started with Auth0 User Authentication </h1>
</div>
<div>
<style>
.hidden {
display: none;
}
label {
margin-bottom: 10px;
display: block;
}
</style>
<br>
<button id="btn-login" class="btn btn-dark" disabled="true">Log in</button>
<button id="btn-logout" class="btn btn-dark" disabled="true">Log out</button>
</div>
</div>
<!-- Video Call Elements Hidden Until the Users Logs in -->
<div class="hidden" id="gated-content">
<p>
You're seeing this content because you're currently
<strong>logged in</strong>.
</p>


<div class="container px-4 mt-4">
<div class="container px-4 mt-4">
<div class="row justify-content-around mt-3">
<div class="row justify-content-around mt-3">
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<h2>Self-View</h2>
<h2>Self-View</h2>
<style>
<style>
#self-view video { /* Flip the display of the local user in self view */
#self-view video { /* Flip the display of the local user in self view */
-webkit-transform: rotateY(180deg); /* Safari, Chrome */
-webkit-transform: rotateY(180deg); /* Safari, Chrome */
-moz-transform: rotateY(180deg); /* Firefox */
-moz-transform: rotateY(180deg); /* Firefox */
transform: rotateY(180deg); /* Microsoft, etc. */
transform: rotateY(180deg); /* Microsoft, etc. */
}
}
</style>
</style>
<div id="self-view"> <!-- Container for the local participant media stream -->
<div id="self-view"> <!-- Container for the local participant media stream -->
<p id="self-view-username"></p>
<p id="self-view-username"></p>
<i class="display-1 bi bi-person-video position-relative"></i>
<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>


<button type="button" class="btn btn-dark" id="btn-join">Join</button>
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<button type="button" class="btn btn-dark" id="btn-leave">Leave</button>
<h2>Remote-View</h2>
</div>
<div id="remote-view"> <!-- Container for the remote participant media stream -->
<p id="remote-view-username"></p>
<div class="col-4 shadow p-3 mb-5 bg-body rounded">
<i class="display-1 bi bi-person-video position-relative"></i>
<h2>Remote-View</h2>
</div>
<div id="remote-view"> <!-- Container for the remote participant media stream -->

<p id="remote-view-username"></p>
<button type="button" class="btn btn-dark" id="btn-invite"><i class="bi bi-clipboard2-plus-fill"></i> Invite</button>
<i class="display-1 bi bi-person-video position-relative"></i>
</div>
</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>
</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="container px-4 py-4 mt-3">
<div class="modal fade" id="token-prompt" tabindex="-1" aria-labelledby="token-prompt-label" aria-hidden="true">
<p id="message"></p>
<div class="modal-dialog">
<p><a href="https://docs.dolby.io/communications-apis/docs/getting-started-with-the-javascript-sdk">Explore More Tutorials</a></p>
<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>
</div>
</div>

<!-- Bootstrap Bundle -->
<!-- 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>
<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 -->
<!-- Dolby.io Starter Application -->
<script type="text/javascript">
<script type="text/javascript">
const shareMessage = (message) => {
const shareMessage = (message) => {
document.getElementById("message").innerText = message;
document.getElementById("message").innerText = message;
}
}


/**
/**
* Start by initializing the Web SDK with an access token. This starter project
* 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.
* utilizes a helper function to provide the token with an API call.
*/
*/
const initializeToken = () => {
const initializeToken = async () => {
console.group("Step 1: Initialize the SDK");
console.group("Step 1: Initialize the SDK");
const token = dolbyio.getAccessToken();
const token = await dolbyio.getAccessToken();
VoxeetSDK.initializeToken(token, () => { console.log("Get a New Access Token"); });
VoxeetSDK.initializeToken(token, () => { console.log("Get a New Access Token"); });
shareMessage("Step 1: Web SDK initialized.");
shareMessage("Step 1: Web SDK initialized.");
console.groupEnd();
console.groupEnd();


return token;
return token;
}
}


/**
/**
* Start a session by establishing a communication link between this client application
* 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
* 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.
* a new session, often this is the name that will be used by the participant.
*/
*/
const openSession = async (sessionName) => {
const openSession = async (sessionName) => {
console.group("Step 2: Open a Session");
console.group("Step 2: Open a Session");
console.log(`Session Name: ${sessionName}`);
console.log(`Session Name: ${sessionName}`);
try {
try {
await VoxeetSDK.session.open({ name: sessionName });
await VoxeetSDK.session.open({ name: sessionName });
shareMessage("Step 2: Session opened.");
shareMessage("Step 2: Session opened.");
} catch (error) {
} catch (error) {
console.error(error);
console.error(error);
shareMessage(`Error opening session: ${error}`);
shareMessage(`Error opening session: ${error}`);
}
}
console.groupEnd();
console.groupEnd();
}
}


/**
/**
* Bi-directional communications for multiple participants occurs in a conference. Initially,
* 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
* 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.
* 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
* This should be in response to a user event so that they may approve media access to the
* microphone and camera.
* microphone and camera.
*/
*/
const createAndJoinConference = async (conferenceAlias, participantName) => {
const createAndJoinConference = async (conferenceAlias, participantName) => {
if (!VoxeetSDK.session.isOpen()) { await openSession(participantName); };
if (!VoxeetSDK.session.isOpen()) { await openSession(participantName); };
console.group("Step 3: Create and Join a Conference");
console.group("Step 3: Create and Join a Conference");
console.log(`Conference Alias: ${conferenceAlias}`);
console.log(`Conference Alias: ${conferenceAlias}`);
const joinOptions = {
const joinOptions = {
constraints: { audio: true, video: true }
constraints: { audio: true, video: true }
};
};
const conferenceOptions = {
const conferenceOptions = {
alias: conferenceAlias
alias: conferenceAlias
}
}
try {
try {
const conference = await VoxeetSDK.conference.create(conferenceOptions);
const conference = await VoxeetSDK.conference.create(conferenceOptions);
await VoxeetSDK.conference.join(conference, joinOptions);
await VoxeetSDK.conference.join(conference, joinOptions);
shareMessage(`Step 3: Conference '${conferenceAlias}' created and joined.`)
shareMessage(`Step 3: Conference '${conferenceAlias}' created and joined.`)
} catch (error) {
} catch (error) {
console.error(error);
console.error(error);
}
}
console.groupEnd();
console.groupEnd();
};
};


/**
/**
* The SDK will trigger server-generated events which we can respond to
* The SDK will trigger server-generated events which we can respond to
* for intended functionality.
* for intended functionality.
*/
*/
const handleConferenceFlow = () => {
const handleConferenceFlow = () => {


// Custom behavior for when there is a media stream added
// Custom behavior for when there is a media stream added
VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
console.log(`Stream Added for ${participant.info.name}`);
console.log(`Stream Added for ${participant.info.name}`);
console.log(` Type: ${stream.type}`);
console.log(` Type: ${stream.type}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);


if (stream.type === "Camera") {
if (stream.type === "Camera") {
shareVideo(participant, stream);
shareVideo(participant, stream);
}
}
});
});


// Custom behavior for when there is a media stream updated which happens once an attendee starts sharing video
// Custom behavior for when there is a media stream updated which happens once an attendee starts sharing video
VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
console.log(`Stream Updated for ${participant.info.name}`);
console.log(`Stream Updated for ${participant.info.name}`);
console.log(` Type: ${stream.type}`);
console.log(` Type: ${stream.type}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);
console.log(` Video Tracks: ${stream.getVideoTracks().length}`);
if (stream.type === "Camera" && stream.getVideoTracks().length) {
if (stream.type === "Camera" && stream.getVideoTracks().length) {
shareVideo(participant, stream);
shareVideo(participant, stream);
}
}
});
});


// Custom behavior for when the app stops receiving a media stream for remote participants
// Custom behavior for when the app stops receiving a media stream for remote participants
VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
console.log(`Stream Removed for ${participant.info.name}`);
console.log(`Stream Removed for ${participant.info.name}`);
const videoNode = document.getElementById(`video-${participant.id}`);
const videoNode = document.getElementById(`video-${participant.id}`);
if (videoNode) {
if (videoNode) {
videoNode.parentNode.removeChild(videoNode);
videoNode.parentNode.removeChild(videoNode);
}
}
});
});


// Custom behavior for when the participant has left the conference
// Custom behavior for when the participant has left the conference
VoxeetSDK.conference.on("left", async () => {
VoxeetSDK.conference.on("left", async () => {
await VoxeetSDK.session.close();
await VoxeetSDK.session.close();
console.log("Session closed.");
console.log("Session closed.");
});
});
}
}


/**
/**
* When a new participant camera media stream is detected, we determine which
* 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
* part of the user interface to update and create a video element that will
* display the incoming stream.
* display the incoming stream.
*/
*/
const shareVideo = (participant, stream) => {
const shareVideo = (participant, stream) => {
console.group("Step 4: Start and Share Video");
console.group("Step 4: Start and Share Video");


let perspective = "self-view";
let perspective = "self-view";
if (VoxeetSDK.session.participant.id !== participant.id) {
if (VoxeetSDK.session.participant.id !== participant.id) {
console.log("Adding media stream for remote user.");
console.log("Adding media stream for remote user.");
perspective = "remote-view";
perspective = "remote-view";
}
}


let videoNode = document.getElementById(`video-${participant.id}`);
let videoNode = document.getElementById(`video-${participant.id}`);
if (videoNode) {
if (videoNode) {
console.log("Video node already created");
console.log("Video node already created");
} else {
} else {
console.log(`Creating a video node: video-${participant.id}`);
console.log(`Creating a video node: video-${participant.id}`);
videoNode = document.createElement("video");
videoNode = document.createElement("video");


videoNode.setAttribute("id", `video-${participant.id}`);
videoNode.setAttribute("id", `video-${participant.id}`);
videoNode.setAttribute("height", "100%");
videoNode.setAttribute("height", "100%");
videoNode.setAttribute("width", "100%");
videoNode.setAttribute("width", "100%");


videoNode.muted = true; // Don't echo local audio
videoNode.muted = true; // Don't echo local audio
videoNode.autoplay = true; // Start right away
videoNode.autoplay = true; // Start right away
videoNode.playsinline = true; // Not full screen
videoNode.playsinline = true; // Not full screen


const videoContainer = document.getElementById(perspective);
const videoContainer = document.getElementById(perspective);
videoContainer.lastElementChild.replaceWith(videoNode);
videoContainer.lastElementChild.replaceWith(videoNode);
videoContainer.firstElementChild.innerText = participant.info.name;
videoContainer.firstElementChild.innerText = participant.info.name;
}
}


navigator.attachMediaStream(videoNode, stream);
navigator.attachMediaStream(videoNode, stream);
shareMessage(`Step 4: Video of participant '${participant.info.name}' started.`);
shareMessage(`Step 4: Video of participant '${participant.info.name}' started.`);
console.groupEnd();
console.groupEnd();
}
}


/**
/**
* When the user decides to leave the conference you should stop sending the audio/video
* When the user decides to leave the conference you should stop sending the audio/video
* stream.
* stream.
*/
*/
const leaveConference = async () => {
const leaveConference = async () => {
console.group("Final Step: Leave the Conference");
console.group("Final Step: Leave the Conference");
try {
try {
await VoxeetSDK.conference.leave();
await VoxeetSDK.conference.leave();
shareMessage("Getting Started Success: Conference has ended.")
shareMessage("Getting Started Success: Conference has ended.")
} catch (error) {
} catch (error) {
console.error(error);
console.error(error);
}
}
console.groupEnd();
console.groupEnd();
}
}


const main = async () => {
const main = async () => {
// Configure the application from query parameter values
// When the web page has finished loading, configure Auth0 client, check the user's login state, and update the UI accordingly.
window.onload = async () => {
await configureClient();
await processLoginState();
// Function below will use initializeToken and openSession functions as callbacks in it after authentication.
await updateUI(initializeToken, openSession);

};
// When user clicks the Log in button, redirect user to Auth0 to access the conference only after authentication
document.getElementById("btn-login").onclick = async () => {
await login();
};
// When user clicks the Log out button, log out and clean Auht0 browser cookies
document.getElementById("btn-logout").onclick = async () => {
await logout();
};
// Configure the conference alias from query parameter values
const queryParams = new URLSearchParams(window.location.search);
const queryParams = new URLSearchParams(window.location.search);
const name = queryParams.get("name") || "developer";
const alias = queryParams.get("alias") || "web-sdk-starter";
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
// When user clicks the Join button, start and join a conference for the given alias
document.getElementById("btn-join").onclick = async () => {
document.getElementById("btn-join").onclick = async () => {
await createAndJoinConference(alias, name);
await createAndJoinConference(alias);
};
};


// Define custom behavior for activity that occurs during a video call
// Define custom behavior for activity that occurs during a video call
handleConferenceFlow();
handleConferenceFlow();


// When user clicks the Invite button, generate a url to join the same conference
// When user clicks the Invite button, generate a url to join the same conference
document.getElementById("btn-invite").onclick = () => {
document.getElementById("btn-invite").onclick = () => {
console.group("Step 5: Invite a remote participant")
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`;
let url = `http://localhost:3000/?alias=${alias}`;
console.log(`Invite a guest with URL: ${url}`);
console.log(`Invite a guest with URL: ${url}`);
shareMessage(`Share the URL copied to your browser clipboard: ${url}`);
shareMessage(`Share the URL copied to your browser clipboard: ${url}`);
navigator.clipboard.writeText(url);
navigator.clipboard.writeText(url);
console.groupEnd();
console.groupEnd();
}
}


// When user clicks the Leave button, end the conference
// When user clicks the Leave button, end the conference
document.getElementById("btn-leave").onclick = async () => {
document.getElementById("btn-leave").onclick = async () => {
await leaveConference();
await leaveConference();
console.log("Getting Started Guide complete, congratulations!");
console.log("Getting Started Guide complete, congratulations!");
};
};
};
};


main();
main();
</script>
</script>
</body>
</body>
</html>
</html>