Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • Official Blog
  • Nearby Places Finder
  • Direction Route Finder
  • Distance & Time Calculator
Menu

Build a Zoom Clone Video Chat and Watch Youtube Videos Together in Node.js Express & Socket.io

Posted on December 25, 2022

 

 

Welcome folks today in this blog post we will be building a zoom clone video chat and watch youtube videos together in node.js express and socket.io using peerjs. All the full source code of the application is shown below.

 

 

Get Started

 

 

In order to get started you need to read the below blog post where I have shown how to build a basic zoom clone video chat in node.js express and socket.io

 

 

Build Zoom Clone Video Chat Web App in Node.js Express and Socket.io Using WebRTC and PeerJS Library

 

 

And after you watch that tutorial you need to clone the github repo of that tutorial as shown below

 

 

git clone https://github.com/WebDevSimplified/Zoom-Clone-With-WebRTC.git

 

 

After you clone the repository using git you can go into the directory and install the node packages as shown below

 

 

cd zoom-clone-with-webrtc

 

 

npm i

 

 

And now your directory structure will look like this

 

 

 

 

Installing the Peerjs Library

 

 

For this application you need the peerjs library globally installed on my machine. You can install it using the npm command

 

 

npm i -g peerjs

 

 

Now you can start the peerjs server at port 3001 as shown below

 

 

peerjs --port 3001

 

 

 

 

And now you can start the express server using the below commnad

 

 

nodemon server.js

 

 

This will start the app at port 3000

 

 

 

 

 

And now you need to little bit modify and tweak this app to allow users to watch their youtube videos together. Now first of all you need to go room.ejs file and copy paste the following code

 

 

views/room.ejs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!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="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script>
    const ROOM_ID = "<%= roomId %>"
  </script>
  <script defer src="https://unpkg.com/peerjs@1.2.0/dist/peerjs.min.js"></script>
  <script src="/socket.io/socket.io.js" defer></script>
  <script src="https://www.youtube.com/iframe_api"></script>
  <script src="script.js" defer></script>
  <title>Document</title>
  <style>
    #video-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, 300px);
      grid-auto-rows: 300px;
    }
 
    video {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  </style>
</head>
 
<body>
  <div class="container">
    <div id="video-grid"></div>
 
    <br><br>
 
    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
    <div style="display: none;" id="player-container" class="container text-center">
      <div class="embed-responsive-item" id="player"></div><br>
    </div>
 
    <br>
 
    <div class="form-group">
      <input class="form-control" type="url" id="url" placeholder="Enter Youtube Video URL" required>
    </div>
    <button onclick="changeVideo()" class="btn btn-danger">Watch Youtube Video Together</button>
    <button onclick="pauseVideo()" class="btn btn-primary">Pause</button>
    <button onclick="playVideo()" class="btn btn-success">Play</button>
    <br><br><br><br><br>
  </div>
</body>
 
</html>

 

 

As you can see we are importing the bootstrap css cdn and also we are also importing the youtube iframe api script tag and then we are adding the iframe player div tag where we will be showing the youtube video. And then we have the input field where we will be taking the url of the video and three buttons for displaying the video and then two buttons for playback. And also we have attached the onclick event listeners to all the buttons.

 

 

 

 

And now we need to modify the script.js file which is the javascript code at the client side inside the public folder

 

 

public/script.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
 
let url = ""
let player
let videoId = "muR3W2EP3W8"
 
const myPeer = new Peer(undefined, {
  host: '/',
  port: '3001'
})
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {}
navigator.mediaDevices.getUserMedia({
  video: true,
  audio: false
}).then(stream => {
  addVideoStream(myVideo, stream)
 
  myPeer.on('call', call => {
    call.answer(stream)
    const video = document.createElement('video')
    call.on('stream', userVideoStream => {
      addVideoStream(video, userVideoStream)
    })
  })
 
  socket.on('changevideo',(videoId) => {
    document.getElementById('player-container').style.display = "block"
    youTubePlayerChangeVideoId(videoId);
  })
 
  socket.on('play',() => {
    player.playVideo()
  })
 
  socket.on('pause',() => {
    player.pauseVideo()
  })
 
  socket.on('user-connected', userId => {
    connectToNewUser(userId, stream)
  })
})
 
function playVideo(){
  socket.emit("play")
}
 
function pauseVideo(){
  socket.emit("pause")
}
 
function changeVideo(){
  document.getElementById("player").innerHTML = "";
  url = document.getElementById('url').value
  videoId = YouTubeGetID(url)
  socket.emit("changevideo",videoId)
  document.getElementById('url').value=""
}
 
function YouTubeGetID(url) {
  var ID = "";
  url = url
    .replace(/(>|<)/gi, "")
    .split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
  if (url[2] !== undefined) {
    ID = url[2].split(/[^0-9a-z_\-]/i);
    ID = ID[0];
  } else {
    ID = url;
  }
  return ID;
}
 
socket.on('user-disconnected', userId => {
  if (peers[userId]) peers[userId].close()
})
 
myPeer.on('open', id => {
  socket.emit('join-room', ROOM_ID, id)
})
 
function connectToNewUser(userId, stream) {
  const call = myPeer.call(userId, stream)
  const video = document.createElement('video')
  call.on('stream', userVideoStream => {
    addVideoStream(video, userVideoStream)
  })
  call.on('close', () => {
    video.remove()
  })
 
  peers[userId] = call
}
 
function addVideoStream(video, stream) {
  video.srcObject = stream
  video.addEventListener('loadedmetadata', () => {
    video.play()
  })
  videoGrid.append(video)
}
 
function youTubePlayerChangeVideoId(videoId) {
  player.cueVideoById({ suggestedQuality: "tiny", videoId: videoId });
  player.pauseVideo();
}
 
function onYouTubeIframeAPIReady() {
  player = new YT.Player("player", {
    height: 500,
    width: "100%",
    videoId: videoId,
    playerVars: {
      playsinline: 1,
      autoplay: 0,
      controls: 1,
    },
    events: {
      onReady: onPlayerReady,
      onStateChange: onPlayerStateChange,
    },
  });
}
 
function onPlayerReady() {
  console.log(true);
}
 
var done = false;
function onPlayerStateChange(event) {
  if (event.data == YT.PlayerState.PLAYING && !done) {
    done = true;
  }
}

 

 

As you can see we have the added the lifecycle methods of the youtube iframe embed api where we are initializing the video player and setting the width and height and then we have the methods which execute when we click the button to change video inside which we are extracting the video id from the youtube url using the custom function where we are using the regular expressions and then we are emitting the event to the server side to change the video. And then the same thing we are doing for play and pause buttons. Here also we are sending the events to server side. And also we have the events which we are listening from the server. Based upon that we are calling playVideo() and pauseVideo() to play and pause the video.

 

 

And lastly we need to edit the server.js file at the backend and copy paste the below code

 

 

server.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const { v4: uuidV4 } = require('uuid')
 
app.set('view engine', 'ejs')
app.use(express.static('public'))
 
app.get('/', (req, res) => {
  res.redirect(`/${uuidV4()}`)
})
 
app.get('/:room', (req, res) => {
  res.render('room', { roomId: req.params.room })
})
 
io.on('connection', socket => {
  socket.on('join-room', (roomId, userId) => {
    socket.join(roomId)
    socket.to(roomId).broadcast.emit('user-connected', userId)
 
    socket.on('disconnect', () => {
      socket.to(roomId).broadcast.emit('user-disconnected', userId)
    })
 
    socket.on('changevideo',(videoId) => {
      io.emit('changevideo',videoId)
    })
 
    socket.on('play',() =>{
      io.sockets.in(roomId).emit("play")
    })
 
    socket.on('pause',() => {
      io.sockets.in(roomId).emit("pause")
    })
  })
})
 
server.listen(4000)

 

 

As you can see we are listening for the events coming from the client side using the on() method and inside which we are emitting the events to the clients connected to the same roomId using the io.sockets.in(roomId) method. Basically it will only send events to all clients connected to the same room. And we are doing it the same thing for play and pause buttons

 

And now if you start the express app the result will look like this as shown below

 

 

 

Recent Posts

  • Android Java Project to Crop,Scale & Rotate Images Selected From Gallery and Save it inside SD Card
  • Android Kotlin Project to Load Image From URL into ImageView Widget
  • Android Java Project to Make HTTP Call to JSONPlaceholder API and Display Data in RecyclerView Using GSON & Volley Library
  • Android Java Project to Download Youtube Video Thumbnail From URL & Save it inside SD Card
  • Android Java Project to Embed Google Maps & Add Markers Using Maps SDK
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme