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

How to Build Jitsi WebRTC App?

Learn how to build a scalable video conferencing application using Jitsi WebRTC with Java/Kotlin.

Introduction to Jitsi WebRTC Technology

What is Jitsi WebRTC?

Jitsi WebRTC is an open-source project that facilitates real-time communication through video, voice, and chat functionalities. Leveraging the power of WebRTC (Web Real-Time Communication), Jitsi provides a robust platform for building scalable and efficient communication applications. The core technologies behind Jitsi include Java and Kotlin, which ensure a strong and flexible foundation for development. Additionally, Jitsi uses a Selective Forwarding Unit (SFU) architecture, which significantly enhances scalability by efficiently managing multiple video streams.

Key Features and Benefits

Jitsi's WebRTC implementation stands out due to its high scalability and flexibility. The SFU architecture allows the server to receive multiple media streams from various participants and forward them selectively to other participants. This method reduces the processing load on clients and optimizes bandwidth usage, making Jitsi suitable for large-scale video conferences. Furthermore, Jitsi's open-source nature means it can be customized to fit specific needs, providing developers with the freedom to create tailored communication solutions.

Importance and Applications

In today's world, real-time communication tools are essential for various sectors, including education, healthcare, business, and social interaction. Jitsi WebRTC is particularly valuable in these contexts because it supports seamless video and voice communication, ensuring that users can connect effortlessly regardless of their location. Whether it's hosting a virtual classroom, conducting remote medical consultations, or facilitating team collaboration, Jitsi WebRTC provides a reliable and scalable solution.
By integrating Jitsi WebRTC into applications, developers can offer users a high-quality communication experience, fostering better connectivity and collaboration. As the demand for real-time communication continues to grow, Jitsi WebRTC remains a crucial tool for developers aiming to build efficient, scalable, and customizable communication platforms.

Getting Started with the Code

To begin developing a Jitsi WebRTC application, you first need to set up a new project. The following steps guide you through initializing a project using Java/Kotlin. This setup will provide the foundation for building your scalable and efficient communication app.

Initializing the Project

[a] Set up your development environment

Ensure you have Java Development Kit (JDK) installed. For Kotlin development, you will also need the Kotlin plugin.


1   # Install JDK (if not already installed)
2   sudo apt-get install openjdk-11-jdk
4   # Install Kotlin (if not already installed)
5   sdk install kotlin

[b] Create a new project directory


1   mkdir JitsiWebRTCApp
2   cd JitsiWebRTCApp

[c] Initialize a new Gradle project

Gradle will help manage dependencies and build the project.


1   gradle init --type java-application

Install Dependencies

To build a Jitsi WebRTC application, you'll need to include several dependencies related to WebRTC and Jitsi. Here’s how to set them up in your build.gradle file.
  • Open the build.gradle file and add the necessary dependencies:


1   dependencies {
2       implementation 'org.jitsi:jitsi-videobridge:2.1'
3       implementation 'org.webrtc:google-webrtc:1.0'
4       implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.4.21'
5   }
  • Sync the Gradle project to download and install the dependencies.

Structure of the Project

Understanding the project structure is crucial for efficient development. Here’s an overview of the key directories and files you’ll work with:
  • src/main/java: Contains your Java/Kotlin source files.
  • src/main/resources: Holds configuration files and static resources.
  • build.gradle: The build configuration file.
  • settings.gradle: Defines project settings.

App Architecture

The architecture of your Jitsi WebRTC app is designed to support high scalability and efficient communication. Here’s an outline of the key components:
  1. Backend Server: Manages signaling and media processing using Jitsi Videobridge.
  2. Frontend Interface: Provides the user interface for joining and managing video calls.
  3. Signaling Mechanism: Handles communication between clients and the server to establish and maintain connections.

Backend Server

  • Jitsi Videobridge: Acts as the media server, forwarding media streams between participants.
  • Signaling Server: Manages the connection setup, participant management, and data exchange.

Frontend Interface

  • Join Screen: Allows users to enter and join the conference.
  • Control Elements: Provide functionalities like mute, unmute, and video on/off.
  • Participant View: Displays video streams from all participants.
By following this structured approach, you can ensure that your Jitsi WebRTC application is not only scalable and efficient but also easy to maintain and extend. The next sections will delve into the specifics of setting up and implementing each component of the application.

Step 1: Get Started with Jitsi Videobridge

Jitsi Videobridge is a crucial component of the Jitsi ecosystem, responsible for routing video streams between participants in a conference. Unlike traditional video conferencing systems that use a Multipoint Control Unit (MCU), Jitsi Videobridge employs a Selective Forwarding Unit (SFU) architecture. This design choice significantly enhances scalability and performance by only forwarding media streams that are necessary for each participant, rather than mixing all streams into one.

Key Features and Benefits

  • Scalability: Supports large numbers of participants without degrading performance.
  • Efficiency: Optimizes bandwidth usage by selectively forwarding streams.
  • Flexibility: Integrates easily with various signaling servers and can be customized to fit specific use cases.
  • Open Source: Allows developers to modify and extend its capabilities as needed.

Setup and Configuration

Setting up Jitsi Videobridge involves several steps, including installation, configuration, and running the service. Here's a step-by-step guide to get you started.

[a] Clone the Jitsi Videobridge Repository

Begin by cloning the Jitsi Videobridge repository from GitHub.


1   git clone https://github.com/jitsi/jitsi-videobridge.git
2   cd jitsi-videobridge

[b] Build the Project

Use Maven to build the project. This will compile the code and download any necessary dependencies.


1   mvn clean install -DskipTests

[c] Configure the Videobridge

After building the project, you need to configure the Videobridge. The main configuration file is located at ~/.jitsi-videobridge/jitsi-videobridge.conf.
Open the configuration file and add the necessary settings:


1   videobridge {
2       http-servers {
3           public {
4               port = 8080
5           }
6       }
7       apis {
8           xmpp-client {
9               enabled = true
10           }
11           rest {
12               enabled = true
13               port = 8080
14           }
15       }
16   }

[d] Run Jitsi Videobridge:

Once configured, you can start the Jitsi Videobridge server.


1   ./jvb.sh --apis=xmpp,rest

[e] Verify the Installation

To ensure the Videobridge is running correctly, you can check the logs for any errors and use a tool like curl to verify the REST API.


1   curl http://localhost:8080/colibri/stats

Code Snippet for Basic Configuration

Here is a basic example of the configuration file (jitsi-videobridge.conf):


1videobridge {
2    http-servers {
3        public {
4            port = 8080
5        }
6    }
7    apis {
8        xmpp-client {
9            enabled = true
10        }
11        rest {
12            enabled = true
13            port = 8080
14        }
15    }

Explanation of Configuration Settings

  • http-servers: Configures the HTTP server that Jitsi Videobridge will use for API interactions.
  • apis: Enables the necessary APIs for communication and control. The xmpp-client API is used for XMPP communication, while the rest API allows for RESTful interactions.
By following these steps, you will have a functional Jitsi Videobridge setup that forms the backbone of your Jitsi WebRTC application. The next parts of the article will guide you through creating the user interface and integrating other essential components of your application.

Step 2: Wireframe All the Components

Component Layout

Creating a well-organized layout is essential for building a robust and user-friendly Jitsi WebRTC application. The main components you need to consider include the join screen, control elements, and participant view. Each component plays a vital role in ensuring a seamless user experience.

Main Components

  1. Join Screen: The entry point for users to join a conference.
  2. Control Elements: User interface elements that allow users to manage their participation (e.g., mute, unmute, video on/off).
  3. Participant View: Displays the video streams of all participants in the conference.

Code Implementation

Now that you have a clear layout, you can start implementing the components in your Jitsi WebRTC application. Below are the code snippets to create the basic layout and components.

[a] HTML Structure

Start by defining the basic HTML structure for your application.


1<!DOCTYPE html>
2<html lang="en">
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>Jitsi WebRTC App</title>
7    <link rel="stylesheet" href="styles.css">
10    <div id="join-screen">
11        <h2>Enter Conference ID</h2>
12        <input type="text" id="conference-id" placeholder="Conference ID">
13        <button id="join-button">Join</button>
14    </div>
15    <div id="controls">
16        <button id="mute-button">Mute</button>
17        <button id="unmute-button">Unmute</button>
18        <button id="video-on-button">Video On</button>
19        <button id="video-off-button">Video Off</button>
20    </div>
21    <div id="participant-view">
22        <!-- Participant videos will be added here dynamically -->
23    </div>
24    <script src="app.js"></script>

[b] CSS Styling

Next, add some basic styling to make the layout presentable. Create a file named styles.css.


1body {
2    font-family: Arial, sans-serif;
3    margin: 0;
4    padding: 0;
5    display: flex;
6    flex-direction: column;
7    align-items: center;
8    background-color: #f0f0f0;
11#join-screen {
12    margin-top: 50px;
13    text-align: center;
16#controls {
17    margin: 20px 0;
18    display: flex;
19    gap: 10px;
22#participant-view {
23    display: flex;
24    flex-wrap: wrap;
25    justify-content: center;
26    gap: 10px;
29#participant-view > div {
30    width: 200px;
31    height: 150px;
32    background-color: #ddd;
33    display: flex;
34    align-items: center;
35    justify-content: center;

[c] JavaScript Logic

Finally, implement the basic JavaScript logic to handle user interactions. Create a file named app.js.


1document.getElementById('join-button').addEventListener('click', function() {
2    const conferenceId = document.getElementById('conference-id').value;
3    if (conferenceId) {
4        // Logic to join the conference
5        console.log('Joining conference:', conferenceId);
6        document.getElementById('join-screen').style.display = 'none';
7        document.getElementById('controls').style.display = 'flex';
8        document.getElementById('participant-view').style.display = 'flex';
9    } else {
10        alert('Please enter a conference ID');
11    }
14document.getElementById('mute-button').addEventListener('click', function() {
15    // Logic to mute
16    console.log('Mute');
19document.getElementById('unmute-button').addEventListener('click', function() {
20    // Logic to unmute
21    console.log('Unmute');
24document.getElementById('video-on-button').addEventListener('click', function() {
25    // Logic to turn video on
26    console.log('Video On');
29document.getElementById('video-off-button').addEventListener('click', function() {
30    // Logic to turn video off
31    console.log('Video Off');

Explanation of the Code

  • HTML: Defines the structure of the join screen, control elements, and participant view.
  • CSS: Provides basic styling for a clean and simple layout.
  • JavaScript: Handles user interactions such as joining a conference, muting, and video control.
By setting up these foundational components, you are well on your way to building a functional and user-friendly Jitsi WebRTC application. The next parts will guide you through implementing specific features and functionalities to enhance your app.

Step 3: Implement Join Screen

Join Screen Design

The join screen is the gateway to your Jitsi WebRTC application. It should be intuitive and straightforward, allowing users to enter a conference ID and join the call with minimal effort. Key design principles for an effective join screen include clarity, simplicity, and responsiveness.

Design Principles

  • Clarity: Ensure that the purpose of the join screen is immediately apparent. Use clear labels and instructions.
  • Simplicity: Minimize the number of input fields and buttons to reduce user friction.
  • Responsiveness: Ensure the join screen works well on various devices, from desktops to smartphones.

UI/UX Considerations

  • Input Field: Clearly labeled with placeholder text to guide users.
  • Join Button: Prominently displayed and easily accessible.
  • Error Handling: Provide feedback if the user tries to join without entering a conference ID.

Code Snippets

Now, let's implement the join screen functionality in detail.

[a] HTML for Join Screen

The HTML structure for the join screen was already set up in Part 4. Here it is for reference:


1<div id="join-screen">
2    <h2>Enter Conference ID</h2>
3    <input type="text" id="conference-id" placeholder="Conference ID">
4    <button id="join-button">Join</button>

[b] CSS for Join Screen

We have already included basic styling in the styles.css file. Here’s the relevant section:


1#join-screen {
2    margin-top: 50px;
3    text-align: center;
6#join-screen input {
7    padding: 10px;
8    font-size: 16px;
11#join-screen button {
12    padding: 10px 20px;
13    font-size: 16px;
14    margin-top: 10px;

[c] JavaScript for Join Screen

Next, we need to add the functionality to handle the user's input and initiate the process to join the conference. This will be part of the app.js file.
  • Event Listener for Join Button:


1document.getElementById('join-button').addEventListener('click', function() {
2    const conferenceId = document.getElementById('conference-id').value;
3    if (conferenceId) {
4        joinConference(conferenceId);
5    } else {
6        alert('Please enter a conference ID');
7    }
  • Join Conference Function:


1function joinConference(conferenceId) {
2    console.log('Joining conference:', conferenceId);
3    // Logic to join the conference
4    document.getElementById('join-screen').style.display = 'none';
5    document.getElementById('controls').style.display = 'flex';
6    document.getElementById('participant-view').style.display = 'flex';
7    // Add code to connect to the Jitsi Videobridge here

Explanation of the Code

  • Event Listener: When the "Join" button is clicked, the event listener checks if a conference ID is entered. If not, it alerts the user to enter an ID.
  • Join Conference Function: This function hides the join screen and displays the controls and participant view. The actual connection logic to the Jitsi Videobridge will be implemented here.

Integrating with Jitsi Videobridge

To join a conference, you'll need to connect to the Jitsi Videobridge server. This involves setting up the connection and handling the signaling process.
Jitsi provides an API to simplify the integration process. Here’s a basic example of how to use the Jitsi Meet API to join a conference:

[a] Include the Jitsi Meet API Script

Add the following script tag to your HTML file, just before the closing </body> tag:


1   <script src='https://meet.jit.si/external_api.js'></script>

[b] Initialize the Jitsi Meet API

Modify the joinConference function to initialize and join the conference using the Jitsi Meet API:


1   function joinConference(conferenceId) {
2       const domain = 'meet.jit.si';
3       const options = {
4           roomName: conferenceId,
5           width: 700,
6           height: 700,
7           parentNode: document.querySelector('#participant-view'),
8           configOverwrite: {},
9           interfaceConfigOverwrite: {}
10       };
11       const api = new JitsiMeetExternalAPI(domain, options);
13       api.addEventListener('videoConferenceJoined', () => {
14           console.log('Successfully joined the conference');
15           document.getElementById('join-screen').style.display = 'none';
16           document.getElementById('controls').style.display = 'flex';
17           document.getElementById('participant-view').style.display = 'flex';
18       });
19   }
By implementing these steps, you've created a functional join screen that allows users to enter a conference ID and join a Jitsi WebRTC session. The next steps will involve adding control elements and managing participant views to enhance the functionality of your application.

Step 4: Implement Controls

Control Elements

In a video conferencing application, control elements are essential for managing the user experience. These controls allow participants to mute/unmute their microphones, turn their video on/off, and perform other interactive functions. Ensuring that these controls are intuitive and responsive enhances the overall usability of your Jitsi WebRTC application.

List of Control Elements

  1. Mute Button: Allows users to mute their microphone.
  2. Unmute Button: Allows users to unmute their microphone.
  3. Video On Button: Allows users to turn on their video feed.
  4. Video Off Button: Allows users to turn off their video feed.

Best Practices for Designing User Controls

  • Visibility: Ensure that control buttons are clearly visible and accessible.
  • Feedback: Provide immediate visual feedback when a control is activated.
  • Responsiveness: Controls should respond quickly to user interactions without noticeable delay.

Code Snippets

Below are the code snippets to implement the control functionalities in your Jitsi WebRTC application.

[a] HTML Structure for Controls

The HTML structure for the controls was already set up in Part 4. Here it is for reference:


1<div id="controls">
2    <button id="mute-button">Mute</button>
3    <button id="unmute-button">Unmute</button>
4    <button id="video-on-button">Video On</button>
5    <button id="video-off-button">Video Off</button>

[b] CSS for Controls

Ensure the controls are styled appropriately. Here’s the relevant section from styles.css:


1#controls {
2    margin: 20px 0;
3    display: flex;
4    gap: 10px;
7#controls button {
8    padding: 10px 20px;
9    font-size: 16px;

JavaScript for Controls

Next, add the functionality to handle user interactions with the control buttons. This will be part of the app.js file.

[c] Event Listeners for Control Buttons


1document.getElementById('mute-button').addEventListener('click', function() {
2    muteMicrophone();
5document.getElementById('unmute-button').addEventListener('click', function() {
6    unmuteMicrophone();
9document.getElementById('video-on-button').addEventListener('click', function() {
10    turnOnVideo();
13document.getElementById('video-off-button').addEventListener('click', function() {
14    turnOffVideo();

[d] Functions to Handle Control Actions


1function muteMicrophone() {
2    // Logic to mute the microphone
3    api.executeCommand('toggleAudio');
4    console.log('Microphone muted');
7function unmuteMicrophone() {
8    // Logic to unmute the microphone
9    api.executeCommand('toggleAudio');
10    console.log('Microphone unmuted');
13function turnOnVideo() {
14    // Logic to turn on the video
15    api.executeCommand('toggleVideo');
16    console.log('Video turned on');
19function turnOffVideo() {
20    // Logic to turn off the video
21    api.executeCommand('toggleVideo');
22    console.log('Video turned off');

Explanation of the Code

  • Event Listeners: These listeners detect clicks on the control buttons and call the appropriate function to handle the action.
  • Control Functions: These functions use the Jitsi Meet API to execute commands that control the audio and video streams.

Integrating with Jitsi Meet API

The Jitsi Meet API provides a straightforward way to interact with the conference and control various aspects of the user’s participation. Here’s how you can integrate the API commands into your control functions.

[a] Initialize Jitsi Meet API

(This should already be done in the joinConference function)


1const api = new JitsiMeetExternalAPI(domain, options);

[b] Using API Commands

Utilize the executeCommand method provided by the Jitsi Meet API to control audio and video.


1function muteMicrophone() {
2    api.executeCommand('toggleAudio');
3    console.log('Microphone muted');
6function unmuteMicrophone() {
7    api.executeCommand('toggleAudio');
8    console.log('Microphone unmuted');
11function turnOnVideo() {
12    api.executeCommand('toggleVideo');
13    console.log('Video turned on');
16function turnOffVideo() {
17    api.executeCommand('toggleVideo');
18    console.log('Video turned off');

Testing the Controls

After implementing the controls, it’s crucial to test each button to ensure it works as expected. Here’s a basic testing checklist:
  • Click the "Mute" button and verify that the microphone is muted.
  • Click the "Unmute" button and verify that the microphone is unmuted.
  • Click the "Video On" button and verify that the video feed is turned on.
  • Click the "Video Off" button and verify that the video feed is turned off.
By following these steps, you have successfully implemented and tested the control elements in your Jitsi WebRTC application. These controls provide essential functionality for managing audio and video during a conference, enhancing the overall user experience. The next steps will guide you through implementing the participant view to display video streams from all participants.

Step 5: Implement Participant View

Participant View Design

The participant view is a crucial component of your Jitsi WebRTC application. It displays the video streams of all participants in a conference, allowing users to see and interact with each other. A well-designed participant view should be responsive, scalable, and easy to navigate.

Design Principles

  1. Responsiveness: Ensure the layout adjusts smoothly across different screen sizes and devices.
  2. Scalability: Handle a varying number of participants efficiently, maintaining performance and usability.
  3. Clarity: Provide a clear and organized display of video streams, avoiding clutter and confusion.

UI/UX Considerations

  • Grid Layout: Use a grid layout to organize video streams uniformly.
  • Dynamic Adjustment: Automatically adjust the layout based on the number of participants.
  • Participant Labels: Include labels or names for each participant to identify them easily.

Code Snippets

Here are the code snippets to implement the participant view in your Jitsi WebRTC application.

HTML for Participant View

The HTML structure for the participant view was set up in Part 4. Here it is for reference:


1<div id="participant-view">
2    <!-- Participant videos will be added here dynamically -->

CSS for Participant View

Add styling to ensure the participant view is responsive and organized. Here’s the relevant section in styles.css:


1#participant-view {
2    display: flex;
3    flex-wrap: wrap;
4    justify-content: center;
5    gap: 10px;
8#participant-view > div {
9    width: 200px;
10    height: 150px;
11    background-color: #ddd;
12    display: flex;
13    align-items: center;
14    justify-content: center;
15    position: relative;
18.participant-label {
19    position: absolute;
20    bottom: 5px;
21    left: 5px;
22    background-color: rgba(0, 0, 0, 0.5);
23    color: white;
24    padding: 2px 5px;
25    font-size: 12px;
26    border-radius: 3px;

JavaScript for Participant View

To dynamically add and manage participant video streams, modify the app.js file as follows:
  • [a] Initialize Jitsi Meet API and Participant Handling:


1let api;
3function joinConference(conferenceId) {
4    const domain = 'meet.jit.si';
5    const options = {
6        roomName: conferenceId,
7        width: '100%',
8        height: '100%',
9        parentNode: document.querySelector('#participant-view'),
10        configOverwrite: {},
11        interfaceConfigOverwrite: {}
12    };
13    api = new JitsiMeetExternalAPI(domain, options);
15    api.addEventListener('videoConferenceJoined', () => {
16        console.log('Successfully joined the conference');
17        document.getElementById('join-screen').style.display = 'none';
18        document.getElementById('controls').style.display = 'flex';
19        document.getElementById('participant-view').style.display = 'flex';
20    });
22    api.addEventListener('participantJoined', handleParticipantJoined);
23    api.addEventListener('participantLeft', handleParticipantLeft);
26function handleParticipantJoined(participant) {
27    console.log('Participant joined:', participant);
28    addParticipantView(participant.id, participant.displayName);
31function handleParticipantLeft(participant) {
32    console.log('Participant left:', participant);
33    removeParticipantView(participant.id);
  • [b] Functions to Add and Remove Participant Views


1function addParticipantView(id, displayName) {
2    const participantContainer = document.createElement('div');
3    participantContainer.id = `participant-${id}`;
4    participantContainer.classList.add('participant');
6    const participantLabel = document.createElement('div');
7    participantLabel.classList.add('participant-label');
8    participantLabel.textContent = displayName || 'Anonymous';
10    participantContainer.appendChild(participantLabel);
11    document.getElementById('participant-view').appendChild(participantContainer);
14function removeParticipantView(id) {
15    const participantContainer = document.getElementById(`participant-${id}`);
16    if (participantContainer) {
17        participantContainer.remove();
18    }

Explanation of the Code

  • Event Listeners: The Jitsi Meet API event listeners handle participants joining and leaving the conference.
  • Participant View Functions: These functions dynamically add or remove video elements in the participant view, ensuring the interface updates in real-time.

Testing the Participant View

After implementing the participant view, test the following scenarios to ensure everything works correctly:
  • When a participant joins, their video stream should appear in the participant view.
  • When a participant leaves, their video stream should be removed from the participant view.
  • The layout should adjust dynamically as participants join and leave, maintaining an organized grid.
By following these steps, you have successfully implemented a responsive and scalable participant view in your Jitsi WebRTC application. This component is essential for providing a clear and organized display of video streams, enhancing the overall user experience. The next step will guide you through running and testing your complete application.

Step 6 - Run Your Code Now

Final Steps

Now that you have implemented the key components of your Jitsi WebRTC application, it's time to run the application and test its functionality. Follow these final steps to ensure your application is up and running smoothly.

Running the Application

[a] Start the Server

Ensure your Jitsi Videobridge server is running. If you haven't started it yet, use the following command:


1   ./jvb.sh --apis=xmpp,rest

[b] Open the Application

Open your HTML file in a web browser. You can do this by navigating to the directory containing your HTML file and opening it directly, or by setting up a local server.


1   # Using Python's HTTP server for quick setup
2   python3 -m http.server
Navigate to http://localhost:8000 in your browser to view the application.

[c] Join a Conference

Enter a conference ID in the join screen and click the "Join" button. This will initiate the connection to the Jitsi Videobridge and display the participant view and controls.

Testing the Application

Ensure all components are working as expected:
  • Join Screen: Verify that entering a conference ID and clicking "Join" successfully connects to the conference.
  • Controls: Test each control button (mute, unmute, video on, video off) to ensure they perform the expected actions.
  • Participant View: Confirm that participant video streams are displayed correctly and adjust dynamically as participants join or leave.


Congratulations! You have successfully built a functional Jitsi WebRTC application using Java/Kotlin, incorporating key features such as a join screen, control elements, and a participant view. This application demonstrates the power and flexibility of Jitsi's open-source tools, providing a robust foundation for building scalable and efficient communication solutions.

Want to level-up your learning? Subscribe now

Subscribe to our newsletter for more tech based insights