Question

In: Computer Science

Create a simple video conferencing web app (P2P or WebRTC). Needs to handle more than one-on-one...

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)

Solutions

Expert Solution

Code Download Link : https://drive.google.com/file/d/1tf6Q7TZjVmUg4i-q53PIeT3HbjdIV_M9/view

Dependencies

  • SimpleWebRTC — the WebRTC library
  • Semantic UI CSS — an elegant CSS framework
  • jQuery — used for selecting elements on the page and event handling.
  • Handlebars — a JavaScript templating library, which we’ll use to generate HTML for the messages
  • Express — NodeJS server.

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

  • Room ID
  • empty chat messages container (to be populated later via JavaScript)
  • input for posting messages.
<!-- 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


Related Solutions

Create a simple video conferencing web app (P2P or WebRTC). Needs to handle more than one-on-one...
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)
Create a simple video conferencing web app (P2P or WebRTC). Needs to handle more than one-on-one...
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)
Create a simple video conferencing web app (P2P or WebRTC). Needs to handle more than one-on-one...
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)
Create a simple python app that allows the user to create a roster of students and...
Create a simple python app that allows the user to create a roster of students and their grade on CUS-1166. Moreover the app needs to calculate the average grade of students added to the roster. 1-To begin with, create a new file n the same working folder as part A (i.e. cus1166_lab1) and name it app.py. Moreover, create a subfolder and name it mymodules. 2-Within mymodules create the files __init__.py , models.py , math_utils.py . 3-In the models.py file define...
Suppose a video conferencing provider, Soom, is planning to pay its next dividend in one year....
Suppose a video conferencing provider, Soom, is planning to pay its next dividend in one year. The dividend will be $1 per share, and Soom expects dividends to grow at 10% per year over the next three years. After that, they expect dividends to grow at 2% per year indefinitely (that is, forever). Suppose that investors have the alternative of buying corporate bonds that will earn 5% per year. Assume the company will next pay a dividend of $1 per...
Summary Develop a Spring Boot Web App which allows user to create a list of the...
Summary Develop a Spring Boot Web App which allows user to create a list of the destinations they have visited during vacations. Your application should allow user to search for a destination based on year of visit. Form View The initial page should have links to either search for a destination , add a new destination, display a list of all destinations that they have visited. The search destination page will have a text field to search by year. The...
Find one video or cartoon example of one of these fallacies on the Web. The example...
Find one video or cartoon example of one of these fallacies on the Web. The example must take the form of a video/cartoon (check out YouTube, for instance, or search for the fallacies in cartoon banks). The Cartoon Network, Family Guy, Stephen Colbert/Jon Stewart, or even just plain old cartoon websites are good places to look. Once you've located the example, paste in a link to the file (embed it) in your Discussion Board thread. Finally, explain why you think...
Part 1; a simple slide show: Create a Web document called l5p1.html that displays one of...
Part 1; a simple slide show: Create a Web document called l5p1.html that displays one of the images from lab 2 in approximately the center of the page; centering need not be exact. Below the image, place three button elements labeled with the names of items from lab 2. (One of them must be the name of the item you chose to display.) Pressing a button should change the displayed image to that of the item named on the button....
For this IP, you will create a very simple drawing app using Android Studio. The purpose...
For this IP, you will create a very simple drawing app using Android Studio. The purpose of this assignment is to give you more building blocks to use when programming apps. For full credit for this assignment, you should complete the following: Create a menu and display menu items on the app bar Detect when the user touches the screen and moves a finger Be able to change the color and width of a line Be able to save an...
Needs to be written in C# Console App! Create a base class BankAccount. Decide what characteristics...
Needs to be written in C# Console App! Create a base class BankAccount. Decide what characteristics are common for checking and saving accounts and include these characteristics in the base class. Define derived classes for checking and savings. In your design , do not allow the banking base account to be instantiated --only the checking and saving classes. Use a Program class to test your design.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT