This content originally appeared on Level Up Coding - Medium and was authored by Taran Arora
This tutorial will show you how to build a video chat app using JavaScript and NodeJS. It will also show you how to use PeerJS, WebRTC, and Socket.io.
Click Here to see live example of the app we’ll be building.
Pre-Project Setup
Here’s what you’ll need:
- NodeJS: Visit the official Node.js website to download and install Node.
- NPM: NPM program gets installed on your computer when you install Node.js.
Project Setup
All the code for this project can be found in the GitHub Repo
- Create an empty directory named video-chat-app.
- Open up your console, navigate to our new directory, and run npm init.
- Fill out the required information to initialize our project.
- Within video-chat-app the directory, and run npm install express ejs socket.io uuid peer. This will install all the dependency that we need to build this application.
- And also as a dev dependency, we will install Nodemon. runnpm install — dev nodemon. This will install nodemon as a dev dependency.
- Create a file named server.js — this file will keep all our server-side logic
Now that we have our project setup, we can start building!
Creating our Server (with Express JS)
The first thing we need to do is get our server up and running. We’re going to use Express to accomplish this. Express is a minimalist web framework for Node.js — Express makes it very easy to create and run a web server with Node.
Let’s create a boilerplate Express starter app file.
// server.js
const express = require(“express”);
const app = express();
const server = require(“http”).Server(app);
app.get(“/”, (req, res) => {
res.status(200).send(“Hello World”);
});
server.listen(3030);
Now we have our server running, We can test our server by running:
> nodemon server.js
Now open your browser and visit: localhost:3000 and you should see Hello World.
Creating our first View
Instead of responding with text when someone visits our root route, we’d like to respond with an HTML file. For this, we’ll be using EJS (Embedded JavaScript). EJS is a templating language.
In order to use EJS in Express, we need to set up our template engine. To setup add this line of code in server.js file.
app.set(‘view engine’, ‘ejs’)
EJS is accessed by default in the views directory. Now create a new folder named views in your directory. Within that views folder, add a file named room.ejs. Think of our room.ejs file as an HTML file for now.
Here’s what our file structure looks like so far:
|-- video-chat-app
|-- views
|-- room.ejs
|-- package.json
|-- server.js
Now we have our boilerplate forroom.ejsthe file. Now we will add our HTML code to room.ejs thefile.
Once you copy the above code, we need to replace our app. js get code:
app.get(‘/’, function (req, res) {
// OLD CODE
res.status(200).send("Hello World");
})
Above is the old code where we send the text ‘Hello World!’ to the client. Instead, we want to send our room.ejs file:
app.get(‘/’, function (req, res) {
// NEW CODE
res.render(‘room’);
})
Now open your browser and visit: localhost:3030 and you should see our room.ejs file being displayed!
Adding a CSS File
This doesn't look good right? That is because we don't have any stylesheet files in our project. So let's add some CSS.
We’ll need to add a new folder to our project called public. Within that folder create a file named style.css and script.js. Here’s our new file structure:
|-- weather-app
|-- views
|-- index.ejs
|-- public
|-- style.css
|-- script.js
|-- package.json
|-- server.js
Express won't allow access to this file by default, so we need to expose it with the following line of code:
app.use(express.static(‘public’));
This code allows us to access all of the static files within the ‘public’ folder.
Finally, we need our CSS. Since this isn’t a CSS course, I’m not going to be going over the specifics, but if you’d like to use my CSS, you can copy it from here.
Once you added CSS. you can visit: localhost:3030/ you will notice your application looks a little nicer.
Setting up our Rooms
By now, your server.jsfile should look like this:
We have one get route, and then we create our server. However, for our application to work, Whenever a new user visits our default route we will redirect him to a unique URL. We will use uuid library to create a random unique URL for each room.
UUID is a javascript library that allows us to create unique Ids. In our application, we will use uuid version 4 to create our unique URL. But first let's import uuid in our server.js file.
const { v4: uuidv4 } = require("uuid");
Now, We will use uuid library to create a random unique id for each room. and we will redirect our user to that room.
app.get(“/”, (req, res) => {
res.redirect(`/${uuidv4()}`);
});
And Before we test this I also wanted to add a view for every unique room and we will pass the current URL to that view.
app.get(“/:room”, (req, res) => {
res.render(“room”, { roomId: req.param.room });
});
We have passedroomId to room.ejs and with this we are done setting our Rooms. and now if you visit localhost:3030. you will be redirected to a unique URL.
Adding Current User Video
We will work on our script.js file that we have created earlier. script.js will contain all our client-side code.
So here what we need to do, we need to get the video stream aka user media, and then we will add that stream to a video element.
let myVideoStream;
const videoGrid = document.getElementById("video-grid");
const myVideo = document.createElement("video");
myVideo.muted = true;
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
});
Now we will create addVideoStream function. which will add the stream to the video element.
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
videoGrid.append(video);
});
};
This code will add a user stream to the video element. you can test this by visiting localhost:3030 and you will see your video popup in the video element
5. Adding the ability to allow others to stream their video
Now it’s time to use Socket.io and PeerJS. For those who don’t know Socket.io allows us to do real-time communication. and PeerJS allow us to implement WebRTC.
First, we will import socket.io and peerjs in our server.js file and listen for join-room event.
// server.js
const express = require(“express”);
const app = express();
const server = require(“http”).Server(app);
const { v4: uuidv4 } = require(“uuid”);
app.set(“view engine”, “ejs”);
const io = require(“socket.io”)(server);
const { ExpressPeerServer } = require(“peer”);
const peerServer = ExpressPeerServer(server, {
debug: true,
});
app.use(“/peerjs”, peerServer);
app.use(express.static(“public”));
app.get(“/”, (req, res) => {
res.redirect(`/${uuidv4()}`);
});
app.get(“/:room”, (req, res) => {
res.render(“room”, { roomId: req.param.room });
});
io.on(“connection”, (socket) => {
socket.on(“join-room”, (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit(“user-connected”, userId);
});
});
server.listen(3030);
Now, We have our server actively listening for a join room event. Next, we will set up our script.js.
// public/script.js
const socket = io(“/”);
const videoGrid = document.getElementById(“video-grid”);
const myVideo = document.createElement(“video”);
myVideo.muted = true;
var peer = new Peer(undefined, {
path: “/peerjs”,
host: “/”,
port: “3030”,
});
let myVideoStream;
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
peer.on(“call”, (call) => {
call.answer(stream);
const video = document.createElement(“video”);
call.on(“stream”, (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on(“user-connected”, (userId) => {
connectToNewUser(userId, stream);
});
});
const connectToNewUser = (userId, stream) => {
const call = peer.call(userId, stream);
const video = document.createElement(“video”);
call.on(“stream”, (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
};
peer.on(“open”, (id) => {
socket.emit(“join-room”, ROOM_ID, id);
});
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener(“loadedmetadata”, () => {
video.play();
videoGrid.append(video);
});
};
Now if a new user joins the room we will see their video.
6. Building User Interface
We are done with our video part. Now let’s do some styling. but first, let’s add some content to room.ejs file. (Add font awesome CDN inside your head tag)
// views/room.ejs
<body>
<div class="header">
<div class="logo">
<h3>Video Chat</h2>
</div>
</div>
<div class="main">
<div class="main__left">
<div class="videos__group">
<div id="video-grid"></div>
</div>
<div class="options">
<div class="options__left">
<div class="options__button">
<i class="fa fa-video-camera" aria-hidden="true"></i>
</div>
<div class="options__button">
<i class="fa fa-microphone" aria-hidden="true"></i>
</div>
</div>
<div class="options__right">
<div class="options__button background__red">
<i class="fa fa-phone" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
<div class="main__right">
<div class="main__chat_window">
<ul class="messages"></ul>
</div>
<div class="main__message_container">
<input id="chat_message" type="text" placeholder="Type message here...">
<div class="options__button">
<i class="fa fa-plus" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
</body>
Next, Lets’s Open our style.css file add some CSS.
@import url(“https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
:root {
— main-darklg: #1d2635;
— main-dark: #161d29;
— primary-color: #2f80ec;
— main-light: #eeeeee;
font-family: “Poppins”, sans-serif;
}
* {
margin: 0;
padding: 0;
}
.header {
display: flex;
justify-content: center;
align-items: center;
height: 8vh;
width: 100%;
background-color: var( — main-darklg);
}
.logo > h3 {
color: var( — main-light);
}
.main {
overflow: hidden;
height: 92vh;
display: flex;
}
.main__left {
flex: 0.7;
display: flex;
flex-direction: column;
}
.videos__group {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
background-color: var( — main-dark);
}
video {
height: 300px;
border-radius: 1rem;
margin: 0.5rem;
width: 400px;
object-fit: cover;
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
}
.options {
padding: 1rem;
display: flex;
background-color: var( — main-darklg);
}
.options__left {
display: flex;
}
.options__right {
margin-left: auto;
}
.options__button {
display: flex;
justify-content: center;
align-items: center;
background-color: var( — primary-color);
height: 50px;
border-radius: 5px;
color: var( — main-light);
font-size: 1.2rem;
width: 50px;
margin: 0 0.5rem;
}
.background__red {
background-color: #f6484a;
}
.main__right {
flex: 0.3;
background-color: #242f41;
}
.main__chat_window {
flex-grow: 1;
}
.main__message_container {
padding: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.main__message_container > input {
height: 50px;
flex: 1;
border-radius: 5px;
padding-left: 20px;
border: none;
}
#video-grid {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
That’s it! Congrats, you have made your video chat app successfully. Now you can deploy it to Heroku and show it to the world.
Live Demo: https://video-chat-app-v1.herokuapp.com/
Source Code: https://github.com/itstaranarora/video-chat-v1
Do follow me on LinkedIn and Github if you find this post useful
Building a Video Chat App with Node.js + Socket.io + WebRTC was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Taran Arora
Taran Arora | Sciencx (2021-03-28T21:48:56+00:00) Building a Video Chat App with Node.js + Socket.io + WebRTC. Retrieved from https://www.scien.cx/2021/03/28/building-a-video-chat-app-with-node-js-socket-io-webrtc/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.