Building custom client web application using Connector SDK

This tutorial will show you how to build your first simple web application using Connector APIs - the VidyoPlatform client SDK

Step 1 - prepare the environment

Nothing complex here - just create index.html file where you markup your web app structure. Let's also put some controls in that you will use further.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
    <link rel="stylesheet" href="main.css" />
    <title>Hello VidyoPlatform</title>
  </head>
  
  <body>
    <main>
      <div class="side-panel">
        <label for="name">Display name:</label>
        <input
          type="text"
          id="name"
          value="User1"
          size="20"
          placeholder="Display name"
          required
        />
        <label for="host">Host:</label>
        <input
          type="text"
          id="hostName"
          value="test.platform.vidyo.io"
          size="20"
          placeholder="Host"
          required
        />
        <label for="roomKey">Room key:</label>
        <input
          type="text"
          id="roomKey"
          value="Ao83tcey3J"
          size="20"
          placeholder="Room key"
          required
        />
        <div class="controls">
          <div>
            <button
              id="btnStart"
              title="Start call"
              onclick="joinCall()"
              class="btnstart"
            ></button>
          </div>
          <button
            id="btnEnd"
            title="End call"
            onclick="endCall()"
            class="btnend"
          ></button>
        </div>
      </div>
      <div class="renderer-container">
        <div id="renderer"></div>
      </div>
    </main>
  </body>
</html>

Also some basic page styles are already included as main.css, here they are:

* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html,
body {
    height: 100%;
    font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
    font-weight: 300;
    background: #363636;
    color: white;
}
main {
    height: 100%;
    display: grid;
    grid-template:
        "s r"
        "s r" 60px / 300px 1fr;
}
@media screen and (max-width: 600px) {
    main {
        grid-template:
            "s s" auto
            "r r" 1fr;
    }
    .side-panel {
        justify-self: center;
        width: 320px;
    }
}
.logo {
    width: 100%;
    margin: 20px 0;
}
.side-panel {
    display: flex;
    flex-direction: column;
    padding: 40px;
    overflow: auto;
    grid-area: s;
}
.side-panel button {
    font-size: 14px;
    border: none;
    border-radius: 3px;
    display: inline-block;
    padding: 6px 18px;
    vertical-align: middle;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    text-align: center;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    box-shadow: none;
    color: #fff;
    height: 36px;
    outline: none;
}
.side-panel input {
    width: 100%;
    height: 36px;
    margin: 20px 0;
    display: inline-block;
    border: none;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 10px;
    border-radius: 3px;
    line-height: 36px;
    font-size: 14px;
    font-weight: 400;
    background-color: hsla(0,0%,100%,.15);
    box-shadow: inset 0 0 0 1px hsl(0deg 0% 100% / 10%);
    color: inherit;
    outline: none;
}
.renderer-container {
    display: grid;
    background-color: #1a1a1a;
    color: inherit;
    grid-area: r;
}

.controls {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}
.controls button {
    position: relative;
    border: none;
    outline: none;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 50%;
    height: 48px;
    width: 48px;
}
.controls button:hover {
    box-shadow: inset 0 0 0 1px hsl(0deg 0% 100% / 10%);
}
.controls button:active {
    background-color: #262626;
}
.controls button:disabled {
    pointer-events: none;
    opacity: 50%;
}
input[type="text"]:disabled {
    background: rgba(239, 239, 239, 0.3);
}
.btnstart {
    background-color: transparent;
    background-image: url(./assets/callStart.png);
    background-size: 28px;
}
.btnend {
    background-color: #6e1e14;
    background-image: url(./assets/end_call.svg);
}
body.in-call .btnstart {
    display: none;
}
body:not(.in-call) .btnend {
    display: none;
}

Step 2 - load Connector SDK files

Include VidyoClient.js scripts into your page

<script
      src="https://static.platform.vidyo.io/vidyoclient/webrtc/latest/VidyoClient.js"
      onload="onVidyoClientLoaded({ state: 'READY', description: 'Native SCIP + WebRTC' })"
    >
</script>

VidyoClient.js is the main and only SDK library that contains all Connector API functions. In other words, you don't need to include any other javascript files for using Connector APIs. Remember to put it within <body>.

Include SDK styles

  <link rel="stylesheet" href="https://static.platform.vidyo.io/vidyoclient/webrtc/latest/VidyoClient.css"/>

This stylesheet is used by VidyoClient.js internally, so it's important to include it into the page in order to prevent layout issues future.

We host the very latest VidyoClient.js and VidyoClient.css files following the links above. So you may load these files to your page from these URLs, however you also can download these files and host them on your web server, if you like.

Load above script onto the page

We need some kind of callback that will tell the app whether VidyoClient.js has been loaded onto the page successfully. For this we use onLoad() callback function of the added script, and it will invoke onVidyoClientLoaded() function below.

function onVidyoClientLoaded(status) {
        console.log("VidyoClient load state - " + status.state);
        switch (status.state) {
          case "READY":
            window.VC = new window.VidyoClientLib.VidyoClient("", () => {
              init();
            });
            console.log("VidyoClient is " + status.state);
            break;

          case "RETRYING":
            console.log(
              "Temporarily unavaible reretrying in" +
                status.nextTimeout / 1000 +
                "seconds"
            );
            break;

          case "FAILED":
            console.log("Failed:" + status.description);
            break;
        }
        return true; // Return true to reload the plugin if not avaible
      }

Step 3 - Create VidyoConnector object

Let's create an init() function and initialize Connector inside it:

     async function init() {
        VC.CreateVidyoConnector({
          viewId: "renderer", // Div ID where the composited video will be rendered.
          viewStyle: "VIDYO_CONNECTORVIEWSTYLE_Default", // Visual style of the composited renderer
          remoteParticipants: 8, // Maximum number of participants to render
          logFileFilter:
            "debug@VidyoClient debug@VidyoSDP debug@VidyoResourceManager",
          logFileName: "",
          userData: 0,
          constraints: {},
        })
          .then((vidyoConnector) => {
            this.vidyoConnector = vidyoConnector;
          })
          .catch((error) => {
            console.log("Create error", error);
          });
      }

In order to instantiate Connector object you will have to call CreateVidyoConnector() function of global VC variable that got initialized when VidyoClient.js loaded onto the page.

viewId parameter of CreateVidyoConnector() function

Let's not stop at each one, but rather review the most important one that you should understand at this point.

viewId: "renderer"

Here we should specify the ID of the DOM element where you want the composited video to be displayed. We suggest to use <div> block for this. You already have this control on your page as

<div class="renderer-container">
      <div id="renderer"></div>
</div>

Important - we strongly suggest to wrap "renderer" div into another outer container. If in future you would like to perform some UI actions with the renderer area (change visibility and so on), it's recommended to manipulate the outer container, and not the "renderer" directly.

Step 4 - Connect to video conference

Host and RoomKey

In previous tutorial you created a room on your tenant and received a RoomLink:

As you may guess, the following chunk of above link is your Host value:

And this one is a RoomKey:

bPFCSWVZnb

Host (or your tenant URL) and RoomKey uniquely identify the meeting room. In other words - these are two values that your client application should get in order to connect to the room.

In a real world typically these values are being sent to the client apps from the backend server application after the room has been created.

After we got the necessary parameters (host, roomKey, displayName) we can proceed with joining the room.

Join the room

In order to join the room you just have to call ConnectToRoomAsGuest() API, and specify your Host and RoomKey values:

const joinCall = async () => {
        await this.vidyoConnector.ConnectToRoomAsGuest({
          host: document.getElementById("hostName").value, // HOST
          roomKey: document.getElementById("roomKey").value, //ROOM KEY
          displayName: document.getElementById("name").value,
          roomPin: "",
          onSuccess: () => {
            console.log(
              `vidyoConnector.ConnectToRoomAsGuest : onSuccess callback received`
            );
            document.body.classList.add("in-call");
            startBtn.disabled = false;
          },
          onFailure: (reason) => {
            console.error(
              "vidyoConnector.Connect : onFailure callback received",
              reason
            );
            handleDisconnect();
          },
          onDisconnected: (reason) => {
            console.log(
              "vidyoConnector.Connect : onDisconnected callback received",
              reason
            );
            handleDisconnect();
          },
        });
      };

For simplicity, in this app we put few <input> controls where you can specify Host and RoomKey parameters. And we pass its values into ConnectToRoomAsGuest() API.

Callbacks

As you might noticed, there are three callback functions in the API call above:

  • onSuccess(): will be fired when connection to the room went successfully. This place is an indicator of the fact that your application has joined the call.

  • onFailure(): will be fired when connection attempt was made, but something went wrong and your app hasn't joined the call. Reason parameter may provide you with details why connection attempt was not successful.

  • onDisconnected(): will be fired when your application disconnected from the call.

Step 5 - Disconnect from video conference

In order to disconnect from ongoing conference you only have to call Disconnect() API:

function endCall() {
        this.vidyoConnector.Disconnect();
      }

Also you might noticed a handleDisconnect() function being called in onFailure() and onDisconnected() callbacks:

function handleDisconnect() {
        document.body.classList.remove("in-call");
        startBtn.disabled = false;
      }

This function simply updates the UI, nothing more. It's up to you how to handle these events in your real app.

Important: When we spin up a VidyoPlatform tenant for you, we by default restrict requests to it from other domain origins. So, when you try to connect to the room on your tenant from your web app hosted at localhost or any custom domain, you may face CORS errors preventing you from joining. In this case please reach out to us with list of the domains you will be hosting your web app on, and we on our side will whitelist these domain for your tenant, and you will be able to connect to the rooms on your tenant.

Last updated