In: Computer Science
Create a simple video conferencing web app (P2P or WebRTC).
Needs to handle more than one-on-one communication and should have option to screen share as well.
(prefer not to use sockets if possible. But if needed then that works too)
Code Download Link : https://drive.google.com/file/d/1tf6Q7TZjVmUg4i-q53PIeT3HbjdIV_M9/view
Dependencies
Project Setup
Go to your workspace and create a folder
simplewebrtc-messenger
. Open the folder in VSCode or
your favorite editor and create the following files and folder
structure:
simplewebrtc-messenger
├── public
│ ├── images
│ │ └── image.png
│ ├── index.html
│ └── js
│ └── app.js
├── README.md
└── server.js
Now let’s install our dependencies:
npm install express handlebars jquery semantic-ui-css simplewebrtc
Create server.js
:
const express = require('express');
const app = express();
const port = 3000;
// Set public folder as root
app.use(express.static('public'));
// Provide access to node_modules folder from the client-side
app.use('/scripts', express.static(`${__dirname}/node_modules/`));
// Redirect all traffic to index.html
app.use((req, res) => res.sendFile(`${__dirname}/public/index.html`));
app.listen(port, () => {
console.info('listening on %d', port);
Next, let’s set up our public/index.html
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="scripts/semantic-ui-css/semantic.min.css">
<title>SimpleWebRTC Demo</title>
<style>
html { margin-top: 20px; }
#chat-content { height: 180px; overflow-y: scroll; }
</style>
</head>
<body>
<!-- Main Content -->
<div class="ui container">
<h1 class="ui header">Simple WebRTC Messenger</h1>
<hr>
</div>
<!-- Scripts -->
<script src="scripts/jquery/dist/jquery.min.js"></script>
<script src="scripts/semantic-ui-css/semantic.min.js"></script>
<script src="scripts/handlebars/dist/handlebars.min.js "></script>
<script src="scripts/simplewebrtc/out/simplewebrtc-with-adapter.bundle.js"></script>
<script src="js/app.js"></script>
</body>
</html>
Next, let’s set up our base client-side JavaScript
code. public/js/app.js
:
window.addEventListener('load', () => {
// Put all client-side code here
});
Now we can run our app:
npm start
Markup
Let’s now work on public/index.html
. For the sake
of simplicity (especially if you’re already familiar with
Handlebars), you can copy the entire markup code from our GitHub
repository. Otherwise, let’s go through things step by step. First
off, copy this code and place it after the <hr>
tag within the ui container
div:
<div class="ui two column stackable grid">
<!-- Chat Section -->
<div class="ui ten wide column">
<div class="ui segment">
<!-- Chat Room Form -->
<div class="ui form">
<div class="fields">
<div class="field">
<label>User Name</label>
<input type="text" placeholder="Enter user name" id="username" name="username">
</div>
<div class="field">
<label>Room</label>
<input type="text" placeholder="Enter room name" id="roomName" name="roomName">
</div>
</div>
<br>
<div class="ui buttons">
<div id="create-btn" class="ui submit orange button">Create Room</div>
<div class="or"></div>
<div id="join-btn" class="ui submit green button">Join Room</div>
</div>
</div>
<!-- Chat Room Messages -->
<div id="chat"></div>
</div>
</div>
<!-- End of Chat Section -->
<!-- Local Camera -->
<div class="ui six wide column">
<h4 class="ui center aligned header" style="margin:0;">
Local Camera
</h4>
<img id="local-image" class="ui large image" src="images/image.png">
<video id="local-video" class="ui large image hidden" autoplay></video>
</div>
</div>
<!-- Remote Cameras -->
<h3 class="ui center aligned header">Remote Cameras</h3>
<div id="remote-videos" class="ui stackable grid">
<div class="four wide column">
<img class="ui centered medium image" src="images/image.png">
</div>
<div class="four wide column">
<img class="ui centered medium image" src="images/image.png">
</div>
<div class="four wide column">
<img class="ui centered medium image" src="images/image.png">
</div>
<div class="four wide column">
<img class="ui centered medium image" src="images/image.png">
</div>
</div>
You should have the following view:
Templates
<!-- Chat Template -->
<script id="chat-template" type="text/x-handlebars-template">
<h3 class="ui orange header">Room ID -> <strong>{{ room }}</strong></h3>
<hr>
<div id="chat-content" class="ui feed"> </div>
<hr>
<div class="ui form">
<div class="ui field">
<label>Post Message</label>
<textarea id="post-message" name="post-message" rows="1"></textarea>
</div>
<div id="post-btn" class="ui primary submit button">Send</div>
</div>
</script>
Next, add the following template, which will be used to display user chat messages:
<!-- Chat Content Template -->
<script id="chat-content-template" type="text/x-handlebars-template">
{{#each messages}}
<div class="event">
<div class="label">
<i class="icon blue user"></i>
</div>
<div class="content">
<div class="summary">
<a href="#"> {{ username }}</a> posted on
<div class="date">
{{ postedOn }}
</div>
</div>
<div class="extra text">
{{ message }}
</div>
</div>
</div>
{{/each}}
</script>
camera:
<!-- Remote Video Template -->
<script id="remote-video-template" type="text/x-handlebars-template">
<div id="{{ id }}" class="four wide column"></div>
</script>
Main App Script
public/js/app.js
// Chat platform
const chatTemplate = Handlebars.compile($('#chat-template').html());
const chatContentTemplate = Handlebars.compile($('#chat-content-template').html());
const chatEl = $('#chat');
const formEl = $('.form');
const messages = [];
let username;
// Local Video
const localImageEl = $('#local-image');
const localVideoEl = $('#local-video');
// Remote Videos
const remoteVideoTemplate = Handlebars.compile($('#remote-video-template').html());
const remoteVideosEl = $('#remote-videos');
let remoteVideosCount = 0;
// Add validation rules to Create/Join Room Form
formEl.form({
fields: {
roomName: 'empty',
username: 'empty',
},
});
Next, let’s initialize our WebRTC code:
// create our WebRTC connection
const webrtc = new SimpleWebRTC({
// the id/element dom element that will hold "our" video
localVideoEl: 'local-video',
// the id/element dom element that will hold remote videos
remoteVideosEl: 'remote-videos',
// immediately ask for camera access
autoRequestMedia: true,
});
// We got access to local camera
webrtc.on('localStream', () => {
localImageEl.hide();
localVideoEl.show();
});
Chat Room Script
$('.submit').on('click', (event) => {
if (!formEl.form('is valid')) {
return false;
}
username = $('#username').val();
const roomName = $('#roomName').val().toLowerCase();
if (event.target.id === 'create-btn') {
createRoom(roomName);
} else {
joinRoom(roomName);
}
return false;
});
Next, we need to declare the createRoom
and
joinRoom
functions. Place the following code before
the click handler code:
// Register new Chat Room
const createRoom = (roomName) => {
console.info(`Creating new room: ${roomName}`);
webrtc.createRoom(roomName, (err, name) => {
showChatRoom(name);
postMessage(`${username} created chatroom`);
});
};
// Join existing Chat Room
const joinRoom = (roomName) => {
console.log(`Joining Room: ${roomName}`);
webrtc.joinRoom(roomName);
showChatRoom(roomName);
postMessage(`${username} joined chatroom`);
};
You may also have noticed that we have
showChatroom
and postMessage
functions
that we haven’t defined yet. Let’s do that now by inserting the
following code before the calling code:
// Post Local Message
const postMessage = (message) => {
const chatMessage = {
username,
message,
postedOn: new Date().toLocaleString('en-GB'),
};
// Send to all peers
webrtc.sendToAll('chat', chatMessage);
// Update messages locally
messages.push(chatMessage);
$('#post-message').val('');
updateChatMessages();
};
// Display Chat Interface
const showChatRoom = (room) => {
// Hide form
formEl.hide();
const html = chatTemplate({ room });
chatEl.html(html);
const postForm = $('form');
// Post Message Validation Rules
postForm.form({
message: 'empty',
});
$('#post-btn').on('click', () => {
const message = $('#post-message').val();
postMessage(message);
});
$('#post-message').on('keyup', (event) => {
if (event.keyCode === 13) {
const message = $('#post-message').val();
postMessage(message);
}
});
};
updateChatMessages
// Update Chat Messages
const updateChatMessages = () => {
const html = chatContentTemplate({ messages });
const chatContentEl = $('#chat-content');
chatContentEl.html(html);
// automatically scroll downwards
const scrollHeight = chatContentEl.prop('scrollHeight');
chatContentEl.animate({ scrollTop: scrollHeight }, 'slow');
};
app.js
:
// Receive message from remote user
webrtc.connection.on('message', (data) => {
if (data.type === 'chat') {
const message = data.payload;
messages.push(message);
updateChatMessages();
}
});
Hit the Create Room button. You’ll be taken to this view. Post some messages to confirm the chat room is working.
Remote Video Camera
// Remote video was added
webrtc.on('videoAdded', (video, peer) => {
const id = webrtc.getDomId(peer);
const html = remoteVideoTemplate({ id });
if (remoteVideosCount === 0) {
remoteVideosEl.html(html);
} else {
remoteVideosEl.append(html);
}
$(`#${id}`).html(video);
$(`#${id} video`).addClass('ui image medium'); // Make video element responsive
remoteVideosCount += 1;
});
After Deployment