End of Life for Twilio Programmable Video - Upgrade to VideoSDKLearn More

Building Real-Time Application Using Janus WebRTC Media Server with JavaScript

Discover how to build real-time applications using the Janus WebRTC Media Server with JavaScript. Get expert tips, tools, and a step-by-step guide for seamless integration.

What is WebRTC?

Web Real-Time Communication (

WebRTC

) is revolutionizing how we engage in real-time communication over the internet. It enables audio, video, and data sharing directly between browsers and devices, without the need for plugins or external software. This technology forms the backbone of applications like video conferencing, online gaming, and peer-to-peer file sharing.

What is Janus WebRTC?

Janus WebRTC stands out as a powerful, open-source WebRTC server that supports a wide range of real-time communication scenarios. Developed by Meetecho, Janus acts as a general-purpose server, enabling developers to implement WebRTC solutions with robust features and high flexibility. Its architecture is designed around plugins, which provide specific functionalities such as video conferencing, streaming, and recording. This modular design allows developers to extend Janus's capabilities easily and tailor it to their specific needs.
At its core, Janus serves as both a Selective Forwarding Unit (

SFU

) and a

SIP

Gateway. As an SFU, Janus efficiently manages multiple media streams, forwarding only the necessary data to each participant, thereby optimizing bandwidth usage and enhancing scalability. Its role as a SIP Gateway allows for seamless integration with traditional telephony systems, bridging the gap between old and new communication technologies.
In the following sections, we will delve into the practical aspects of setting up and using Janus WebRTC. We will cover everything from installation to implementing key features, providing a step-by-step guide to building your own WebRTC application with Janus. Whether you are a seasoned developer or new to WebRTC, this guide will equip you with the knowledge and tools to leverage Janus for your real-time communication needs.

Let`s Build Real-Time Chat Application Using Janus WebRTC Media Server

Getting Started with the Code

In this section, we will guide you through the initial steps of setting up your Janus WebRTC application. From cloning the repository to understanding the project structure, we'll cover everything you need to get started.

Create a New Janus WebRTC App

To begin, you need to clone the Janus WebRTC repository from GitHub. Open your terminal and execute the following command:

bash

1git clone https://github.com/meetecho/janus-gateway.git
This command will download the latest Janus source code to your local machine.

Install Janus Dependencies

Before you can build Janus, you need to install its dependencies. Janus relies on several libraries, including libnice, libsrtp, and libssl. Install these dependencies using the package manager of your operating system. For instance, on Ubuntu, you can use:

bash

1sudo apt-get install libmicrohttpd-dev libjansson-dev libssl-dev libsofia-sip-ua-dev libglib2.0-dev libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev
Once the dependencies are installed, navigate to the Janus directory and build the project:

bash

1cd janus-gateway
2sh autogen.sh
3./configure
4make
5sudo make install

Structure of the Project

After installation, it’s essential to understand the project structure. The main directories include:
  • cfg: Contains configuration files for Janus and its plugins.
  • html: Holds the sample web applications.
  • plugins: Directory for Janus plugins that extend its functionality.
  • src: Source code for the Janus core server.

App Architecture

janus-webrtc-app
Janus's architecture is modular and plugin-based. Each plugin serves a specific purpose, such as handling video rooms, streaming, or SIP communication. This architecture allows you to enable only the functionalities you need and extend Janus with custom plugins as required.
Now that you have a basic understanding of the project setup and architecture, we can move on to configuring Janus and creating your first WebRTC application. In the next sections, we'll guide you through setting up your environment and writing the necessary code to get your application up and running.

Step 1: Get Started with Configuration

Configuring Janus for the first time involves setting up its core settings and enabling the necessary plugins for your application. Follow these steps to ensure a smooth setup process.

Configuring Janus for First Use

Begin by navigating to the cfg directory within the Janus installation folder. Here, you will find several configuration files, including janus.cfg, which is the main configuration file for Janus. Open janus.cfg in your preferred text editor:

bash

1cd /usr/local/etc/janus
2sudo nano janus.cfg

[a] Core Configuration

In janus.cfg, you’ll configure the core settings of Janus. Key settings include:

[b] General settings

Enable or disable debug logging and set the log level.

ini

1  [general]
2  debug_level = 4

[c] Network settings

Configure the IP addresses and ports for Janus to listen on.

ini

1  [nat]
2  stun_server = stun.l.google.com:19302

[d] WebSocket settings

Enable WebSocket support for signaling between the client and server.

ini

1  [websockets]
2  ws = yes
3  ws_port = 8188

Plugin Configuration

Next, you need to configure the plugins that Janus will use. For example, to enable the video room plugin, open the janus.plugin.videoroom.cfg file:

bash

1sudo nano janus.plugin.videoroom.cfg
Ensure the plugin is enabled and configure any specific settings required:

ini

1[general]
2enabled = yes

Setting Up WebSockets and HTTP Endpoints

WebSockets are crucial for real-time communication in WebRTC. In janus.cfg, ensure WebSocket support is enabled:

ini

1[websockets]
2ws = yes
3ws_port = 8188
Similarly, configure the HTTP endpoints for REST API calls:

ini

1[http]
2http = yes
3http_port = 8088

Core and Plugin-Specific Configurations

Make sure to review and adjust any other core and plugin-specific settings as needed. Save and close the configuration files once you've made the necessary changes.

Starting Janus Media Server

After configuring Janus, start the server to apply your changes:

bash

1sudo janus
Janus should now be running with your specified configurations. In the next section, we will set up the environment and create a basic HTML/JavaScript front end to interact with Janus, initializing a WebRTC connection and handling signaling.
This step completes the initial setup and configuration, preparing Janus to handle WebRTC sessions effectively.

Step 2: Wireframe All the Components

Now that you have configured Janus, it's time to set up the environment and create the front end for your WebRTC application. This involves creating a basic HTML/JavaScript interface to interact with Janus, initializing WebRTC connections, and handling the signaling process.

Setting Up the Environment

To start, create a new directory for your web application and navigate into it:

bash

1mkdir janus-webrtc-app
2cd janus-webrtc-app
Inside this directory, create an index.html file for your application's front end:

HTML

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Janus WebRTC Demo</title>
5</head>
6<body>
7  <h1>Janus WebRTC Demo</h1>
8  <div>
9    <video id="localVideo" autoplay muted></video>
10    <video id="remoteVideo" autoplay></video>
11  </div>
12  <button id="startButton">Start</button>
13  <button id="callButton">Call</button>
14  <button id="hangupButton">Hang Up</button>
15  <script src="app.js"></script>
16</body>
17</html>

Initializing a WebRTC Connection

Next, create an app.js file to handle the WebRTC connection logic:

JavaScript

1let localStream;
2let remoteStream;
3let janusConnection;
4let janusPlugin;
5
6document.getElementById('startButton').addEventListener('click', start);
7document.getElementById('callButton').addEventListener('click', call);
8document.getElementById('hangupButton').addEventListener('click', hangUp);
9
10async function start() {
11  localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
12  document.getElementById('localVideo').srcObject = localStream;
13  initializeJanus();
14}
15
16function initializeJanus() {
17  Janus.init({
18    debug: "all",
19    callback: function() {
20      janusConnection = new Janus({
21        server: 'ws://localhost:8188/',
22        success: function() {
23          janusConnection.attach({
24            plugin: "janus.plugin.videoroom",
25            success: function(pluginHandle) {
26              janusPlugin = pluginHandle;
27              // Additional plugin initialization can be done here
28            },
29            error: function(error) {
30              console.error("Error attaching plugin", error);
31            }
32          });
33        },
34        error: function(error) {
35          console.error("Error connecting to Janus", error);
36        }
37      });
38    }
39  });
40}
41
42function call() {
43  // Logic to start a WebRTC call using Janus
44}
45
46function hangUp() {
47  // Logic to hang up a WebRTC call
48}

Explanation of the Signaling Process and Handling ICE Candidates

In the initializeJanus function, we initialize the Janus library and establish a connection to the Janus server via WebSocket. Once connected, we attach to the janus.plugin.videoroom plugin, which will handle our video call functionality. The signaling process involves exchanging SDP (Session Description Protocol) messages and ICE (Interactive Connectivity Establishment) candidates between the client and the Janus server to establish a peer-to-peer connection.
In the start function, we capture the local media stream using getUserMedia, which prompts the user to grant access to their camera and microphone. The captured stream is then displayed in the localVideo element.
The call and hangUp functions will contain the logic to initiate and terminate WebRTC calls, which we will implement in the following steps.
By setting up this basic structure, you have laid the groundwork for your WebRTC application. In the next sections, we will build on this foundation to implement a join screen, user controls, and participant views.

Step 3: Implement Join Screen

With the basic environment and initial setup complete, the next step is to create a user-friendly join screen that allows participants to enter and join a WebRTC session. This involves designing the user interface and implementing the necessary JavaScript code to handle user input and session management.

Building the Join Screen UI

First, update your index.html file to include a join screen where users can enter their names and join a session:

HTML

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Janus WebRTC Demo</title>
5</head>
6<body>
7  <h1>Janus WebRTC Demo</h1>
8  <div id="joinScreen">
9    <input type="text" id="username" placeholder="Enter your name">
10    <button id="joinButton">Join</button>
11  </div>
12  <div id="videoScreen" style="display:none;">
13    <video id="localVideo" autoplay muted></video>
14    <video id="remoteVideo" autoplay></video>
15    <button id="startButton">Start</button>
16    <button id="callButton">Call</button>
17    <button id="hangupButton">Hang Up</button>
18  </div>
19  <script src="https://cdn.jsdelivr.net/npm/janus-gateway@0.11.5/janus.js"></script>
20  <script src="app.js"></script>
21</body>
22</html>
Next, update app.js to handle the join screen logic:

JavaScript

1let localStream;
2let remoteStream;
3let janusConnection;
4let janusPlugin;
5let myUsername;
6let myRoom = 1234; // Example room ID
7
8document.getElementById('joinButton').addEventListener('click', joinRoom);
9document.getElementById('startButton').addEventListener('click', start);
10document.getElementById('callButton').addEventListener('click', call);
11document.getElementById('hangupButton').addEventListener('click', hangUp);
12
13function joinRoom() {
14  myUsername = document.getElementById('username').value;
15  if (myUsername === "") {
16    alert("Please enter a username");
17    return;
18  }
19  document.getElementById('joinScreen').style.display = 'none';
20  document.getElementById('videoScreen').style.display = 'block';
21  initializeJanus();
22}
23
24async function start() {
25  localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
26  document.getElementById('localVideo').srcObject = localStream;
27  janusPlugin.createOffer({
28    media: { data: true },
29    success: function(jsep) {
30      const body = { request: "join", room: myRoom, ptype: "publisher", display: myUsername };
31      janusPlugin.send({ message: body, jsep: jsep });
32    },
33    error: function(error) {
34      console.error("WebRTC error:", error);
35    }
36  });
37}
38
39function initializeJanus() {
40  Janus.init({
41    debug: "all",
42    callback: function() {
43      janusConnection = new Janus({
44        server: 'ws://localhost:8188/',
45        success: function() {
46          janusConnection.attach({
47            plugin: "janus.plugin.videoroom",
48            success: function(pluginHandle) {
49              janusPlugin = pluginHandle;
50              janusPlugin.send({
51                message: { request: "create", room: myRoom }
52              });
53            },
54            error: function(error) {
55              console.error("Error attaching plugin", error);
56            }
57          });
58        },
59        error: function(error) {
60          console.error("Error connecting to Janus", error);
61        }
62      });
63    }
64  });
65}
66
67function call() {
68  // Logic to start a WebRTC call using Janus
69}
70
71function hangUp() {
72  // Logic to hang up a WebRTC call
73}

Managing User States and Sessions on the Server-Side

The joinRoom function captures the username input and toggles the display between the join screen and the video screen. It then calls initializeJanus to set up the connection with the Janus server.
In the initializeJanus function, after successfully attaching to the janus.plugin.videoroom plugin, we send a request to create or join a room. The start function captures the local media stream and creates an offer to join the specified room.
By implementing these changes, you create a join screen that allows users to enter a session and sets up the WebRTC connection. In the next steps, we'll add more functionality to handle calls and manage user interactions within the session.

Step 4: Implement Controls

Having set up the join screen and initialized the WebRTC connection, the next step is to implement user controls. These controls will enable users to manage their audio and video streams, such as muting/unmuting their microphone and turning their camera on/off. Additionally, we'll handle sending commands to Janus to manage these states.

Adding User Controls

First, update your index.html file to include buttons for muting and toggling the video:

HTML

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Janus WebRTC Demo</title>
5</head>
6<body>
7  <h1>Janus WebRTC Demo</h1>
8  <div id="joinScreen">
9    <input type="text" id="username" placeholder="Enter your name">
10    <button id="joinButton">Join</button>
11  </div>
12  <div id="videoScreen" style="display:none;">
13    <video id="localVideo" autoplay muted></video>
14    <video id="remoteVideo" autoplay></video>
15    <button id="startButton">Start</button>
16    <button id="callButton">Call</button>
17    <button id="hangupButton">Hang Up</button>
18    <button id="muteButton">Mute</button>
19    <button id="videoButton">Video Off</button>
20  </div>
21  <script src="https://cdn.jsdelivr.net/npm/janus-gateway@0.11.5/janus.js"></script>
22  <script src="app.js"></script>
23</body>
24</html>
Next, update app.js to handle the new controls:

JavaScript

1let localStream;
2let remoteStream;
3let janusConnection;
4let janusPlugin;
5let myUsername;
6let myRoom = 1234; // Example room ID
7
8document.getElementById('joinButton').addEventListener('click', joinRoom);
9document.getElementById('startButton').addEventListener('click', start);
10document.getElementById('callButton').addEventListener('click', call);
11document.getElementById('hangupButton').addEventListener('click', hangUp);
12document.getElementById('muteButton').addEventListener('click', toggleMute);
13document.getElementById('videoButton').addEventListener('click', toggleVideo);
14
15function joinRoom() {
16  myUsername = document.getElementById('username').value;
17  if (myUsername === "") {
18    alert("Please enter a username");
19    return;
20  }
21  document.getElementById('joinScreen').style.display = 'none';
22  document.getElementById('videoScreen').style.display = 'block';
23  initializeJanus();
24}
25
26async function start() {
27  localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
28  document.getElementById('localVideo').srcObject = localStream;
29  janusPlugin.createOffer({
30    media: { data: true },
31    success: function(jsep) {
32      const body = { request: "join", room: myRoom, ptype: "publisher", display: myUsername };
33      janusPlugin.send({ message: body, jsep: jsep });
34    },
35    error: function(error) {
36      console.error("WebRTC error:", error);
37    }
38  });
39}
40
41function initializeJanus() {
42  Janus.init({
43    debug: "all",
44    callback: function() {
45      janusConnection = new Janus({
46        server: 'ws://localhost:8188/',
47        success: function() {
48          janusConnection.attach({
49            plugin: "janus.plugin.videoroom",
50            success: function(pluginHandle) {
51              janusPlugin = pluginHandle;
52              janusPlugin.send({
53                message: { request: "create", room: myRoom }
54              });
55            },
56            error: function(error) {
57              console.error("Error attaching plugin", error);
58            }
59          });
60        },
61        error: function(error) {
62          console.error("Error connecting to Janus", error);
63        }
64      });
65    }
66  });
67}
68
69function call() {
70  // Logic to start a WebRTC call using Janus
71}
72
73function hangUp() {
74  // Logic to hang up a WebRTC call
75}
76
77function toggleMute() {
78  const audioTracks = localStream.getAudioTracks();
79  if (audioTracks.length > 0) {
80    audioTracks[0].enabled = !audioTracks[0].enabled;
81    document.getElementById('muteButton').textContent = audioTracks[0].enabled ? 'Mute' : 'Unmute';
82  }
83}
84
85function toggleVideo() {
86  const videoTracks = localStream.getVideoTracks();
87  if (videoTracks.length > 0) {
88    videoTracks[0].enabled = !videoTracks[0].enabled;
89    document.getElementById('videoButton').textContent = videoTracks[0].enabled ? 'Video Off' : 'Video On';
90  }
91}

Handling User Inputs and Sending Commands to Janus

The toggleMute and toggleVideo functions handle the logic for muting/unmuting the microphone and toggling the video on/off. They manipulate the enabled property of the respective media tracks in the localStream. The button text updates accordingly to reflect the current state.
When a user clicks the mute or video button, the corresponding function is called, and the state of the local media tracks is changed. The Janus server receives these updates through the WebRTC connection, ensuring that other participants are aware of the changes.
By implementing these controls, you allow users to manage their media streams effectively during a session. In the next section, we will focus on creating the participant view to display video and audio streams from all session participants.

Get Free 10,000 Minutes Every Months

No credit card required to start.

Step 5: Implement Participant View

The participant view is a crucial part of any WebRTC application, as it displays the video and audio streams from all participants in the session. In this section, we'll extend our HTML and JavaScript code to handle multiple participant streams, ensuring they are displayed correctly on the user interface.

Creating the Participant View

First, update your index.html file to include a container for participant videos:

HTML

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Janus WebRTC Demo</title>
5  <style>
6    .participant {
7      display: inline-block;
8      margin: 10px;
9    }
10    .participant video {
11      width: 200px;
12      height: 150px;
13    }
14  </style>
15</head>
16<body>
17  <h1>Janus WebRTC Demo</h1>
18  <div id="joinScreen">
19    <input type="text" id="username" placeholder="Enter your name">
20    <button id="joinButton">Join</button>
21  </div>
22  <div id="videoScreen" style="display:none;">
23    <div id="localParticipant" class="participant">
24      <video id="localVideo" autoplay muted></video>
25    </div>
26    <div id="remoteParticipants"></div>
27    <button id="startButton">Start</button>
28    <button id="callButton">Call</button>
29    <button id="hangupButton">Hang Up</button>
30    <button id="muteButton">Mute</button>
31    <button id="videoButton">Video Off</button>
32  </div>
33  <script src="https://cdn.jsdelivr.net/npm/janus-gateway@0.11.5/janus.js"></script>
34  <script src="app.js"></script>
35</body>
36</html>
Next, update app.js to handle multiple participant streams:

JavaScript

1let localStream;
2let remoteStream;
3let janusConnection;
4let janusPlugin;
5let myUsername;
6let myRoom = 1234; // Example room ID
7let remoteFeed = null;
8
9document.getElementById('joinButton').addEventListener('click', joinRoom);
10document.getElementById('startButton').addEventListener('click', start);
11document.getElementById('callButton').addEventListener('click', call);
12document.getElementById('hangupButton').addEventListener('click', hangUp);
13document.getElementById('muteButton').addEventListener('click', toggleMute);
14document.getElementById('videoButton').addEventListener('click', toggleVideo);
15
16function joinRoom() {
17  myUsername = document.getElementById('username').value;
18  if (myUsername === "") {
19    alert("Please enter a username");
20    return;
21  }
22  document.getElementById('joinScreen').style.display = 'none';
23  document.getElementById('videoScreen').style.display = 'block';
24  initializeJanus();
25}
26
27async function start() {
28  localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
29  document.getElementById('localVideo').srcObject = localStream;
30  janusPlugin.createOffer({
31    media: { data: true },
32    success: function(jsep) {
33      const body = { request: "join", room: myRoom, ptype: "publisher", display: myUsername };
34      janusPlugin.send({ message: body, jsep: jsep });
35    },
36    error: function(error) {
37      console.error("WebRTC error:", error);
38    }
39  });
40}
41
42function initializeJanus() {
43  Janus.init({
44    debug: "all",
45    callback: function() {
46      janusConnection = new Janus({
47        server: 'ws://localhost:8188/',
48        success: function() {
49          janusConnection.attach({
50            plugin: "janus.plugin.videoroom",
51            success: function(pluginHandle) {
52              janusPlugin = pluginHandle;
53              janusPlugin.send({
54                message: { request: "create", room: myRoom }
55              });
56            },
57            error: function(error) {
58              console.error("Error attaching plugin", error);
59            },
60            onmessage: function(msg, jsep) {
61              let event = msg["videoroom"];
62              if (event) {
63                if (event === "joined") {
64                  let publishers = msg["publishers"];
65                  for (let i in publishers) {
66                    let id = publishers[i]["id"];
67                    let display = publishers[i]["display"];
68                    newRemoteFeed(id, display);
69                  }
70                } else if (event === "event") {
71                  // Handle events
72                }
73              }
74              if (jsep) {
75                janusPlugin.handleRemoteJsep({ jsep: jsep });
76              }
77            },
78            onlocalstream: function(stream) {
79              // Do nothing
80            },
81            onremotestream: function(stream) {
82              let remoteVideo = document.createElement('video');
83              remoteVideo.autoplay = true;
84              remoteVideo.srcObject = stream;
85              document.getElementById('remoteParticipants').appendChild(remoteVideo);
86            }
87          });
88        },
89        error: function(error) {
90          console.error("Error connecting to Janus", error);
91        }
92      });
93    }
94  });
95}
96
97function newRemoteFeed(id, display) {
98  janusConnection.attach({
99    plugin: "janus.plugin.videoroom",
100    opaqueId: "remoteFeed" + id,
101    success: function(pluginHandle) {
102      remoteFeed = pluginHandle;
103      let body = { request: "join", room: myRoom, ptype: "subscriber", feed: id };
104      remoteFeed.send({ message: body });
105    },
106    error: function(error) {
107      console.error("Error attaching plugin", error);
108    },
109    onmessage: function(msg, jsep) {
110      if (jsep) {
111        remoteFeed.createAnswer({
112          jsep: jsep,
113          media: { audioSend: false, videoSend: false },
114          success: function(jsep) {
115            let body = { request: "start", room: myRoom };
116            remoteFeed.send({ message: body, jsep: jsep });
117          },
118          error: function(error) {
119            console.error("WebRTC error:", error);
120          }
121        });
122      }
123    },
124    onremotestream: function(stream) {
125      let remoteVideo = document.createElement('video');
126      remoteVideo.autoplay = true;
127      remoteVideo.srcObject = stream;
128      document.getElementById('remoteParticipants').appendChild(remoteVideo);
129    }
130  });
131}
132
133function call() {
134  // Logic to start a WebRTC call using Janus
135}
136
137function hangUp() {
138  // Logic to hang up a WebRTC call
139}
140
141function toggleMute() {
142  const audioTracks = localStream.getAudioTracks();
143  if (audioTracks.length > 0) {
144    audioTracks[0].enabled = !audioTracks[0].enabled;
145    document.getElementById('muteButton').textContent = audioTracks[0].enabled ? 'Mute' : 'Unmute';
146  }
147}
148
149function toggleVideo() {
150  const videoTracks = localStream.getVideoTracks();
151  if (videoTracks.length > 0) {
152    videoTracks[0].enabled = !videoTracks[0].enabled;
153    document.getElementById('videoButton').textContent = videoTracks[0].enabled ? 'Video Off' : 'Video On';
154  }
155}

Handling Multiple Streams with Janus SFU

The onremotestream callback in the initializeJanus function handles the display of remote streams. When a remote stream is received, a new video element is created, and the stream is assigned to it. This video element is then appended to the remoteParticipants div.
The newRemoteFeed function attaches a new instance of the janus.plugin.videoroom plugin for each new remote participant. It handles the signaling and stream negotiation required to receive remote streams.
By implementing these changes, you can display video and audio streams from multiple participants in your WebRTC session, creating a dynamic and interactive user experience. In the final section, we'll discuss how to run and test your application to ensure everything works smoothly.

Step 6: Run Your Code Now

With the code and configuration in place, it's time to run your Janus WebRTC application and test its functionality. Follow these steps to start the Janus server and load your application in a web browser:

[a] Start the Janus Server

Open a terminal and navigate to the Janus installation directory. Start the Janus server by running:

bash

1   sudo janus
Ensure the server starts without any errors.

[b] Open the Web Application

Open your web browser and navigate to the directory where your HTML file is located. Open the index.html file. For example:

bash

1   file:///path/to/your/janus-webrtc-app/index.html

[c] Join and Test

Enter a username, click "Join," and then click "Start." Allow access to your camera and microphone. Test the "Call" and "Hang Up" buttons to ensure functionality.

Troubleshooting Common Issues

  • WebSocket Connection Errors: Ensure the WebSocket server URL in your app.js matches the Janus server's WebSocket configuration.
  • Media Access Issues: Check browser permissions for accessing the camera and microphone.
  • Plugin Errors: Ensure the necessary plugins are enabled and correctly configured in the Janus server.

Conclusion

In this article, we building real-time chat application using Janus WebRTC Media Server with JavaScript from scratch. We've covered everything from installing Janus, configuring it, creating a user-friendly join screen, implementing essential controls, and displaying participant views. By following these steps, you now have a foundational understanding of how to leverage Janus WebRTC for real-time communication applications. Janus's flexibility and plugin-based architecture make it a powerful tool for developing scalable and customizable WebRTC solutions.

Want to level-up your learning? Subscribe now

Subscribe to our newsletter for more tech based insights

FAQ