index.html comms-getting-started

Created Diff never expires
61 removals
287 lines
86 additions
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>
<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>
<!-- 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>
</div>


<button type="button" class="btn btn-dark" id="btn-join">Join</button>
<button type="button" class="btn btn-dark" id="btn-join">Join</button>
<button type="button" class="btn btn-dark" id="btn-leave">Leave</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>
</div>


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


<div class="container px-4 py-4 mt-3">
<button type="button" class="btn btn-dark" id="btn-invite"><i class="bi bi-clipboard2-plus-fill"></i> Invite</button>
<p id="message"></p>
</div>
<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>

<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>
</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>