Quick Start for Conference in Angular JS
VideoSDK empowers you to seamlessly integrate the video calling feature into your Angular JS application within minutes.
In this quickstart, you'll explore the group calling feature of VideoSDK. Follow the step-by-step guide to integrate it within your application.
Prerequisites
Before proceeding, ensure that your development environment meets the following requirements:
- Video SDK Developer Account (Not having one, follow Video SDK Dashboard)
- Have Node and NPM installed on your device.
One should have a VideoSDK account to generate token. Visit VideoSDK dashboard to generate token
Getting Started with the Code!
Follow the steps to create the environment necessary to add video calls into your app. You can also find the code sample for quickstart here.
Install Video SDK
Import VideoSDK using the <script>
tag or Install it using the following npm command. Make sure you are in your app directory before you run this command.
- <script>
- npm
- yarn
<html>
<head>
....
</head>
<body>
.....
<script src="https://sdk.videosdk.live/js-sdk/0.0.86/videosdk.js"></script>
</body>
</html>
npm install @videosdk.live/js-sdk
yarn add @videosdk.live/js-sdk
Structure of the project
Your project structure should look like this.
root
├── app
│ ├── lib
│ ├── angular.min.js
│ ├── app.js
├── content
│ ├── css
│ ├── styles.css
├── views
│ ├── joinScreen.html
│ ├── meetingContainer.html
│ ├── topBar.html
├── config.js
├── index.js
You will be working on the following files:
- joinScreen.html: Responsible for creating a basic UI for the joinScreen functionality.
- meetingContainer.html: Responsible for creating a simple grid-screen for the meeting.
- topBar.html: Responsible for creating a basic topbar with webcam, mic and leave meeting buttons.
- config.js: Responsible for storing the token.
- app.js: Responsible for rendering components such as meeting view, joinscreen and topbar.
Step 1 : Design the user interface (UI)
Create an HTML file that will render the join-screen
, top-bar
and meeting-container
components.
1.1 First, Create the UI for the joinScreen
functionality.
<div
id="joinPage"
class="main-bg"
style="display: flex"
ng-controller="myController"
>
<div style="display: flex; flex-direction: column; margin-left: 8px">
<h3>AngularJS quickstart with Videosdk</h3>
<form name="myForm" style="display: flex">
<div style="margin-right: 8px">
<button
class="btn secondary text-white"
id="meetingStartButton"
ng-click="createMeeting()"
>
Create Meeting
</button>
</div>
<p>OR</p>
<div style="margin-left: 10px; margin-right: 16px">
<input
class="text-input"
type="text"
ng-model="meetingId"
placeholder="Enter meeting id"
/>
<p ng-show="showMeetingIdError" class="input-err">
Please enter valid meeting Id
</p>
</div>
<div>
<button
class="btn secondary text-white"
id="meetingJoinButton"
ng-click="validateMeeting()"
>
Join Meeting
</button>
</div>
</form>
</div>
</div>
Output
1.2 Next, Create the topBar
UI.
<div
style="height: 70px; background-color: lightgray"
ng-controller="myController"
ng-show="showMeetingScreen"
id="top-bar"
>
<div class="top-bar-div">
<div>
<p style="margin-top: 0px; margin-bottom: 0px; font-weight: 700">
MeetingId: {{meetingId}}
</p>
</div>
<div style="display: flex; align-items: center; margin-top: 8px">
<button style="cursor: pointer" ng-click="toggleWebcam()">
Toggle Webcam
</button>
<button style="margin-left: 4px; cursor: pointer" ng-click="toggleMic()">
Toggle Mic
</button>
<button class="leave-btn" ng-click="leaveMeeting()">Leave Meeting</button>
</div>
</div>
</div>
Output
1.3 Subsequently, create the meetingContainer.html
file.
<div
style=" display: flex; flex-direction: column; overflow-y: auto; max-height: calc(100vh - 90px);
"
ng-controller="myController"
>
<div class="container">
<div id="participant-grid-container" class="row"></div>
</div>
</div>
Finally, assemble the components by creating the index.html
file and incorporating all the previously created components into it.
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<base href="/" />
<title>Angular JS - Videosdk</title>
<link href="content/css/styles.css" rel="stylesheet" type="text/css" />
<script src="app/lib/angular.min.js"></script>
<script src="config.js"></script>
<script src="app/app.js"></script>
</head>
<body>
<top-bar />
<div ng-show="showJoinScreen">
<join-screen />
</div>
<div ng-show="showMeetingScreen">
<meeting-container />
</div>
<script src="https://sdk.videosdk.live/js-sdk/0.0.86/videosdk.js"></script>
</body>
</html>
Step 2 : Implement Join Screen
Configure the token in the config.js
file, which you can obtain from the VideoSDK Dashbord.
// Auth token will be used to generate a meeting and connect to it
"use strict";
angular.module("config", []).constant("ENV", {
token: "YOUR_TOKEN", // Add token here
});
Next, retrieve all the elements from the DOM and declare the following variables in the app.js
file. Then, add an event listener to the join and create meeting buttons.
var myApp = angular.module("myApp", ["config"]);
myApp.config(function () {});
myApp.run(function () {});
// create directives of component
myApp.directive("joinScreen", [
function () {
return {
restrict: "E",
templateUrl: "views/joinScreen.html",
transclude: true,
controller: "myController",
replace: true,
};
},
]);
myApp.directive("topBar", [
function () {
return {
restrict: "E",
templateUrl: "views/topBar.html",
transclude: true,
controller: "myController",
replace: true,
};
},
]);
myApp.directive("meetingContainer", [
function () {
return {
restrict: "E",
templateUrl: "views/meetingContainer.html",
transclude: true,
controller: "myController",
replace: true,
};
},
]);
myApp.controller("myController", function ($scope, ENV) {
// variable initialization
$scope.name = "Homi J. Bhabha";
$scope.meetingId = "";
$scope.showMeetingIdError = false;
$scope.showMeetingScreen = false;
$scope.showJoinScreen = true;
$scope.meeting = null;
// Getting Elements from DOM
$scope.participantGridContainer = document.getElementById(
"participant-grid-container"
);
// API request for create meeting
$scope.createMeeting = function () {
const url = "https://api.videosdk.live/v2/rooms";
const config = {
headers: {
Authorization: ENV.token,
"Content-Type": "application/json",
},
};
$http
.post(url, { name: $scope.name }, config)
.then(function (response) {
const { roomId } = response.data;
$scope.meetingId = roomId;
$scope.initMeeting();
})
.catch(function (error) {
alert("error", error);
});
};
// API request for validate meeting
$scope.validateMeeting = function () {
const url = `https://api.videosdk.live/v2/rooms/validate/${$scope.meetingId}`;
const config = {
headers: {
Authorization: ENV.token,
"Content-Type": "application/json",
},
};
$http
.get(url, config)
.then(function (response) {
if (response.data.roomId === $scope.meetingId) {
$scope.showMeetingIdError = false;
$scope.initMeeting();
}
})
.catch(function (error) {
$scope.showMeetingIdError = true;
console.log("error", error);
});
};
});
Step 3 : Initialize meeting
Following that, initialize the meeting using the initMeeting()
function and proceed to join the meeting.
// Initialize meeting
$scope.initMeeting = function () {
window.VideoSDK.config(ENV.token); // required;
var meeting = window.VideoSDK.initMeeting({
meetingId: $scope.meetingId, // required
name: $scope.name, // required
micEnabled: true, // optional, default: true
webcamEnabled: true, // optional, default: true
});
meeting.join();
$scope.meeting = meeting;
if ($scope.meeting) {
$scope.handleMeetingEvents($scope.meeting);
var showJoinScreenMessage = document.createElement("div");
var topBar = document.getElementById("top-bar");
topBar.style.display = "none";
showJoinScreenMessage.setAttribute("id", "show-join-screen-message");
showJoinScreenMessage.innerHTML = "Please wait to join meeting...";
showJoinScreenMessage.style.color = "black";
showJoinScreenMessage.style.fontSize = "20px";
showJoinScreenMessage.style.fontWeight = "bold";
showJoinScreenMessage.style.marginTop = "20px";
showJoinScreenMessage.style.marginLeft = "20px";
$scope.participantGridContainer.appendChild(showJoinScreenMessage);
}
};
Output
Step 4 : Handle Meeting Events
Once the meeting is successfully initialized, create the participant grid and manage events such as meeting-joined
, meeting-left
, and participant events.
// variable initialization
$scope.localParticipant = null;
$scope.participants = [];
// creating Name Element
$scope.createNameElement = function (participant) {
var nameElement = document.createElement("div");
nameElement.setAttribute("id", `name-container-${participant.id}`);
nameElement.innerHTML = participant.displayName.charAt(0).toUpperCase();
nameElement.style.backgroundColor = "black";
nameElement.style.color = "white";
nameElement.style.textAlign = "center";
nameElement.style.padding = "32px";
nameElement.style.borderRadius = "100%";
nameElement.style.fontSize = "20px";
return nameElement;
};
// for handle meeting events
$scope.handleMeetingEvents = function (meeting) {
$scope.localParticipant = meeting.localParticipant;
$scope.participants = meeting.participants;
// creating participant Grid
$scope.participantGridGenerator = function ({ participant }) {
var participantGridItem = document.createElement("div");
participantGridItem.style.backgroundColor = "lightgrey";
participantGridItem.style.borderRadius = "10px";
participantGridItem.style.height = "300px";
participantGridItem.style.width = "320px";
participantGridItem.style.marginTop = "8px";
participantGridItem.style.display = "flex";
participantGridItem.style.alignItems = "center";
participantGridItem.style.justifyContent = "center";
participantGridItem.style.position = "relative";
participantGridItem.setAttribute(
"id",
`participant-grid-item-${participant.id}`
);
participantGridItem.setAttribute("class", "col-4");
var participantMediaElement1 = document.createElement("div");
participantMediaElement1.setAttribute(
"id",
`participant-media-container-${participant.id}`
);
var nameElement = $scope.createNameElement(participant);
$scope.participantGridContainer.appendChild(participantGridItem);
participantGridItem.appendChild(participantMediaElement1);
participantMediaElement1.appendChild(nameElement);
var participantMediaElement = document.getElementById(
`participant-media-container-${participant.id}`
);
return {
participantMediaElement,
};
};
if (meeting) {
$scope.showJoinScreen = false;
$scope.showMeetingScreen = true;
}
// meeting joined event
meeting.on("meeting-joined", function () {
var showJoinScreenMessage = document.getElementById(
"show-join-screen-message"
);
var topBar = document.getElementById("top-bar");
showJoinScreenMessage.style.display = "none";
topBar.style.display = "block";
const { participantMediaElement } = $scope.participantGridGenerator({
participant: meeting.localParticipant,
});
meeting.localParticipant.on("stream-enabled", (stream) => {
$scope.handleStreamEnabled(
stream,
meeting.localParticipant,
true,
participantMediaElement
);
});
meeting.localParticipant.on("stream-disabled", (stream) => {
$scope.handleStreamDisabled(
stream,
meeting.localParticipant,
true,
participantMediaElement
);
});
});
// meeting left event
meeting.on("meeting-left", () => {
// remove all children nodes from participant grid container
while ($scope.participantGridContainer.firstChild) {
$scope.participantGridContainer.removeChild(
$scope.participantGridContainer.firstChild
);
}
$scope.showMeetingScreen = false;
$scope.showJoinScreen = true;
});
//remote participant events
// participant joined
meeting.on("participant-joined", (participant) => {
console.log("New Participant Joined: ", participant.id);
participant.on("stream-enabled", (stream) => {
//...
});
participant.on("stream-disabled", (stream) => {
//...
});
});
// participant left
meeting.on("participant-left", (participant) => {
//...
});
};
Step 5 : Create the Media Elements
In this step, Create a function to generate audio and video elements for displaying both local and remote participants. Set the corresponding media track based on whether it's a video or audio stream.
myApp.controller("myController", function ($scope, $http, ENV) {
// creating video element
$scope.createVideoElement = function (
stream,
participant,
participantMediaElement
) {
var video = document.createElement("video");
var mediaStream = new MediaStream();
mediaStream.addTrack(stream.track);
video.srcObject = mediaStream;
video.autoplay = true;
video.id = `v-${participant.id}`;
video.style.marginTop = "6px";
video.style.marginLeft = "4px";
video.style.marginRight = "4px";
video.style.width = "320px";
video.style.height = "300px";
video.style.objectFit = "cover";
video.style.transform = "rotate('90')";
video.style.borderRadius = "10px";
video.setAttribute("playsinline", true);
var videoElement = document.createElement("div");
videoElement.setAttribute("id", `video-container-${participant.id}`);
participantMediaElement.appendChild(videoElement);
videoElement.appendChild(video);
var cornerDisplayName = document.createElement("div");
cornerDisplayName.setAttribute("id", `name-container-${participant.id}`);
cornerDisplayName.style.position = "absolute";
cornerDisplayName.style.bottom = "16px";
cornerDisplayName.style.left = "16px";
cornerDisplayName.style.color = "white";
cornerDisplayName.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
cornerDisplayName.style.padding = "2px";
cornerDisplayName.style.borderRadius = "2px";
cornerDisplayName.style.fontSize = "12px";
cornerDisplayName.style.fontWeight = "bold";
cornerDisplayName.style.zIndex = "1";
cornerDisplayName.style.padding = "4px";
cornerDisplayName.innerHTML =
participant.displayName.length > 15
? participant.displayName.substring(0, 15) + "..."
: participant.displayName;
videoElement.appendChild(cornerDisplayName);
};
// creating audio element
$scope.createAudioElement = function (
stream,
participant,
participantMediaElement
) {
var audio = document.createElement("audio");
var mediaStream = new MediaStream();
mediaStream.addTrack(stream.track);
audio.srcObject = mediaStream;
audio.autoplay = true;
audio.muted;
audio.id = `audio-${participant.id}`;
var audioElement = document.createElement("div");
audioElement.setAttribute("id", `audio-container-${participant.id}`);
participantMediaElement.appendChild(audioElement);
audioElement.appendChild(audio);
};
// handle streams
$scope.handleStreamEnabled = function (
stream,
participant,
isLocal,
participantMediaElement
) {
if (stream.kind == "video") {
var nameElement = document.getElementById(
`name-container-${participant.id}`
);
participantMediaElement.removeChild(nameElement);
$scope.createVideoElement(stream, participant, participantMediaElement);
}
if (!isLocal) {
if (stream.kind == "audio") {
$scope.createAudioElement(stream, participant, participantMediaElement);
}
}
};
$scope.handleStreamDisabled = function (
stream,
participant,
isLocal,
participantMediaElement
) {
if (stream.kind == "video") {
var videoElement = document.getElementById(
`video-container-${participant.id}`
);
var nameElement = $scope.createNameElement(participant);
participantMediaElement.removeChild(videoElement);
participantMediaElement.appendChild(nameElement);
}
if (!isLocal) {
if (stream.kind == "audio") {
var audioElement = document.getElementById(
`audio-container-${participant.id}`
);
participantMediaElement.removeChild(audioElement);
}
}
};
});
Step 6 : Handle participant events
Thereafter, implement the events related to the participants and the stream.
Following are the events to be executed in this step:
-
participant-joined
: When a remote participant joins, this event will trigger. In the event callback, create video and audio elements previously defined for rendering their video and audio streams. -
participant-left
: When a remote participant leaves, this event will trigger. In the event callback, remove the corresponding video and audio elements. -
stream-enabled
: This event manages the media track of a specific participant by associating it with the appropriate video or audio element. -
stream-disabled
: This event manages the media track of a specific participant, when they toggle their camera or mic by associating it with the appropriate video or audio element.
$scope.handleMeetingEvents = function (meeting) {
//...
// participant joined
meeting.on("participant-joined", (participant) => {
console.log("New Participant Joined: ", participant.id);
var { participantMediaElement } = $scope.participantGridGenerator({
participant: participant,
});
participant.setQuality("high");
participant.on("stream-enabled", (stream) => {
$scope.handleStreamEnabled(
stream,
participant,
false,
participantMediaElement
);
});
participant.on("stream-disabled", (stream) => {
$scope.handleStreamDisabled(
stream,
participant,
false,
participantMediaElement
);
});
});
// participants left
meeting.on("participant-left", (participant) => {
var participantGridItem = document.getElementById(
`participant-grid-item-${participant.id}`
);
$scope.participantGridContainer.removeChild(participantGridItem);
});
};
Output
Step 7 : Implement Controls
Next, implement the meeting controls such as toggleMic, toggleWebcam and leave meeting.
myApp.controller("myController", function ($scope, $http, ENV) {
//...
$scope.isWebcamOn = true;
$scope.isMicOn = true;
$scope.handleMeetingEvents = function (meeting) {
//..
// Toggle Webcam in Meeting
$scope.toggleWebcam = function () {
if ($scope.isWebcamOn) {
$scope.meeting.disableWebcam();
} else {
$scope.meeting.enableWebcam();
}
$scope.isWebcamOn = !$scope.isWebcamOn;
};
// Toggle Webcam in Meeting
$scope.toggleMic = function () {
if ($scope.isMicOn) {
$scope.meeting.muteMic();
} else {
$scope.meeting.unmuteMic();
}
};
// leave meeting
$scope.leaveMeeting = function () {
$scope.meeting.leave();
$scope.showMeetingScreen = false;
$scope.showJoinScreen = true;
};
};
});
Run your code
Once you have completed all the steps mentioned above, run your application using the code block below.
live-server --port=8000
Final Output
You have completed the implementation of a customized video calling app in Angular JS using VideoSDK. To explore more features, go through Basic and Advanced features.
You can checkout the complete quick start example here.
Got a Question? Ask us on discord