Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 31, 2020 08:27 am GMT

Let's build a video conferencing app

Hello Everyone,

In this article we will see how to build a video conferencing app.

Prerequisites:
Basics of Webrtc

To implement this we will be using the following libraries:

  1. React
  2. Nodejs
  3. simple-peer
  4. socket.io
  5. chance

Setup Server:

touch app.jsyarn add express socket.io
Enter fullscreen mode Exit fullscreen mode
const express = require('express');const http = require('http');const app = express();const server = http.createServer(app);const io = require('socket.io')(server);const users = {};const socketRoomMap = {};io.on('connection', (socket) => {  socket.on('join-room', (roomId, userDetails) => {    // adding all user to a room so that we can broadcast messages    socket.join(roomId);    // adding map users to room    if (users[roomId]) {      users[roomId].push({ socketId: socket.id, ...userDetails });    } else {      users[roomId] = [{ socketId: socket.id, ...userDetails }];    }    // adding map of socketid to room    socketRoomMap[socket.id] = roomId;    const usersInThisRoom = users[roomId].filter(      (user) => user.socketId !== socket.id    );    /* once a new user has joined sending the details of     users who are already present in room. */    socket.emit('users-present-in-room', usersInThisRoom);  });  socket.on('initiate-signal', (payload) => {    const roomId = socketRoomMap[socket.id];    let room = users[roomId];    let name = '';    if (room) {      const user = room.find((user) => user.socketId === socket.id);      name = user.name;    }    /* once a peer wants to initiate signal,     To old user sending the user details along with signal */    io.to(payload.userToSignal).emit('user-joined', {      signal: payload.signal,      callerId: payload.callerId,      name,    });  });  /* once the peer acknowledge signal sending the   acknowledgement back so that it can stream peer to peer. */  socket.on('ack-signal', (payload) => {    io.to(payload.callerId).emit('signal-accepted', {      signal: payload.signal,      id: socket.id,    });  });  socket.on('disconnect', () => {    const roomId = socketRoomMap[socket.id];    let room = users[roomId];    if (room) {      room = room.filter((user) => user.socketId !== socket.id);      users[roomId] = room;    }    // on disconnect sending to all users that user has disconnected    socket.to(roomId).broadcast.emit('user-disconnected', socket.id);  });});server.listen(3001);
Enter fullscreen mode Exit fullscreen mode

Here we use socket to transmit the user details and webrtc signals between multiple peers.

Setup the Client:

npx create-react-app webrtc-video-call-reactcd webrtc-video-call-reactyarn add socket.io-client simple-peer chance
Enter fullscreen mode Exit fullscreen mode
import React from 'react';import { BrowserRouter, Route, Switch } from 'react-router-dom';import Home from './Home';import Room from './Room';const App = () => (  <div className='App'>    <BrowserRouter>      <Switch>        <Route path='/' exact component={Home} />        <Route path='/room/:roomId' component={Room} />      </Switch>    </BrowserRouter>  </div>);export default App;
Enter fullscreen mode Exit fullscreen mode

Here we have 2 routes /home and /room/:roomId . In /home we will give the option to create room or join room. In /room/:roomId is where we will render the video streams from multiple users.

import React, { useState } from 'react';import * as Chance from 'chance';const chance = new Chance();const Home = ({ history }) => {  const [roomId, setRoomId] = useState('');  return (    <div style={{ marginTop: 10, marginLeft: 10 }}>      <input        type='text'        value={roomId}        onChange={(e) => setRoomId(e.target.value)}      ></input>      <button        type='button'        onClick={() => {          if (!roomId) {            alert('RoomId is required');            return;          }          history.push(`/room/${roomId}`);        }}      >        Join Room      </button>      <button        type='button'        onClick={() => {          const id = chance.guid();          history.push(`/room/${id}`);        }}      >        Create Room      </button>    </div>  );};export default Home;
Enter fullscreen mode Exit fullscreen mode
import React, { useEffect, useRef, useState } from 'react';import io from 'socket.io-client';import Peer from 'simple-peer';import * as Chance from 'chance';import Video from './Video';const chance = new Chance();const Room = (props) => {  const [userDetails, setUserDetails] = useState({    id: chance.guid(),    name: chance.name(),  });  const [peers, setPeers] = useState([]);  const socketRef = useRef();  const refVideo = useRef();  const peersRef = useRef([]);  const roomId = props.match.params.roomId;  useEffect(() => {    navigator.mediaDevices      .getUserMedia({ video: true, audio: true })      .then((stream) => {        refVideo.current.srcObject = stream;        socketRef.current = io.connect('http://localhost:3001');        // sending the user details and roomid to join in the room        socketRef.current.emit('join-room', roomId, userDetails);        socketRef.current.on('users-present-in-room', (users) => {          const peers = [];          // To all users who are already in the room initiating a peer connection          users.forEach((user) => {            const peer = createPeer(              user.socketId,              socketRef.current.id,              stream            );            peersRef.current.push({              peerId: user.socketId,              peer,              name: user.name,            });            peers.push({              peerId: user.socketId,              peerObj: peer,            });          });          setPeers(peers);        });        // once the users initiate signal we will call add peer        // to acknowledge the signal and send the stream        socketRef.current.on('user-joined', (payload) => {          const peer = addPeer(payload.signal, payload.callerId, stream);          peersRef.current.push({            peerId: payload.callerId,            peer,            name: payload.name,          });          setPeers((users) => [            ...users,            { peerId: payload.callerId, peerObj: peer },          ]);        });        // once the signal is accepted calling the signal with signal        // from other user so that stream can flow between peers        socketRef.current.on('signal-accepted', (payload) => {          const item = peersRef.current.find((p) => p.peerId === payload.id);          item.peer.signal(payload.signal);        });        // if some user is disconnected removing his references.        socketRef.current.on('user-disconnected', (payload) => {          const item = peersRef.current.find((p) => p.peerId === payload);          if (item) {            item.peer.destroy();            peersRef.current = peersRef.current.filter(              (p) => p.peerId !== payload            );          }          setPeers((users) => users.filter((p) => p.peerId !== payload));        });      });  }, []);  function createPeer(userToSignal, callerId, stream) {    const peer = new Peer({      initiator: true,      trickle: false,      stream,    });    peer.on('signal', (signal) => {      socketRef.current.emit('initiate-signal', {        userToSignal,        callerId,        signal,      });    });    return peer;  }  function addPeer(incomingSignal, callerId, stream) {    const peer = new Peer({      initiator: false,      trickle: false,      stream,    });    peer.on('signal', (signal) => {      socketRef.current.emit('ack-signal', { signal, callerId });    });    peer.signal(incomingSignal);    return peer;  }  return (    <div style={{ display: 'flex', flexWrap: 'wrap' }}>      <div style={{ display: 'flex', flexDirection: 'column' }}>        <video muted ref={refVideo} autoPlay playsInline />        <span>{userDetails.name}</span>      </div>      {peers.map((peer, index) => {        return (          <Video            key={peersRef.current[index].peerId}            peer={peer.peerObj}            name={peersRef.current[index].name}          />        );      })}    </div>  );};export default Room;
Enter fullscreen mode Exit fullscreen mode

This room component will take care of connecting to the peers, sending and receiving signal with the help of our socket server and simple-peer.

Start the server, client and open the url in multiple devices to see it in action.

Output

Please feel free fork and play with the source code.

Source:
Client
Server

Please like and share if you find this interesting.


Original Link: https://dev.to/kannndev/let-s-build-a-video-conferencing-app-pp

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To