OpenVidu WebRTC is an open-source platform that allows developers to build real-time video calling applications using WebRTC technology. It provides client and server SDKs that handle signaling, session management, and media routing through a Mediasoup-based media server. Developers choose OpenVidu when they need full control over their media infrastructure, data privacy, and ultra-low latency streaming without relying on third-party SaaS providers.
Building a real-time video application from scratch using raw WebRTC APIs is notoriously difficult due to complex signaling, NAT traversal, and media routing challenges. Developers often spend weeks managing ICE candidates, handling SDP renegotiation, and building a reliable signaling server. OpenVidu WebRTC solves this by providing a ready-to-use, open-source platform that abstracts the hard parts of WebRTC while letting you keep everything on your own infrastructure. Whether you are building a telehealth application, an online classroom, or a live-streaming platform, having control over your media server is a major advantage for data privacy and cost management. In this guide, you will learn the core architecture of OpenVidu, its key features, how to deploy it using Docker, and how it compares to other real-time communication solutions like VideoSDK.
What Is OpenVidu WebRTC?
OpenVidu WebRTC is defined as an open-source WebRTC platform designed to facilitate the development of real-time video and audio applications. It works by wrapping the complex WebRTC standard into a set of simple client and server SDKs, allowing developers to create video sessions without dealing directly with SDP negotiation or ICE candidates. The platform relies on a Selective Forwarding Unit (SFU) architecture, specifically using Mediasoup as its media router. This allows OpenVidu to handle many participants in a session by routing media streams efficiently rather than mixing them, which saves significant CPU resources.
OpenVidu provides SDKs for multiple platforms, including JavaScript, React, Angular, iOS, Android, and Unity, making it a versatile choice for cross-platform development. The platform is maintained by a dedicated open-source community and is widely used by organizations that need to keep their video data within specific geographic or regulatory boundaries. By offering a self-hosted alternative to commercial WebRTC providers, OpenVidu enables developers to build highly customized video applications without recurring per-minute usage fees.
Core Architecture of OpenVidu WebRTC
The architecture of OpenVidu WebRTC revolves around a client-server model where the browser communicates with an OpenVidu Server. When a user wants to join a video call, the client SDK initiates a WebSocket connection to the OpenVidu Server for signaling. The server then coordinates with the Mediasoup router to establish the actual media paths over WebRTC. The OpenVidu Server manages sessions, participants, and tokens, while Mediasoup handles the heavy lifting of receiving and forwarding audio and video tracks to other participants. This separation of concerns allows the signaling layer to remain lightweight while the media server scales to handle high-definition video streams.
The entire flow is designed to be highly resilient, with automatic reconnection logic built into the client SDKs to handle temporary network drops. When a client connects, the OpenVidu Server orchestrates the SDP offer and answer exchange, gathering ICE candidates to punch through firewalls. Once the WebRTC connection is established, the media flows directly between the client and the Mediasoup router, bypassing the signaling server for optimal performance.

Signaling and Session Management
OpenVidu handles signaling through a dedicated REST API and WebSocket connection. When a client wants to join a session, the application backend requests a token from the OpenVidu Server. This token authenticates the user and grants access to a specific session. The client SDK uses this token to establish a connection, after which the OpenVidu Server orchestrates the WebRTC negotiation. Session management includes handling participant joins, leaves, and publishing or subscribing to streams.
The server maintains the state of the room, ensuring that when a new participant joins, they receive the existing participants' streams. If a participant drops unexpectedly, the server cleans up their resources and notifies the remaining participants. This lifecycle management is crucial for maintaining a stable video conference, especially in scenarios where users might switch between mobile networks and Wi-Fi.
Media Routing with Mediasoup
Mediasoup is a powerful Node.js and C++ based WebRTC SFU that OpenVidu uses under the hood. It excels at low-latency media routing by keeping the media processing close to the network layer. When a participant publishes their camera feed, Mediasoup receives the RTP packets and forwards them to all subscribed participants. This approach is highly efficient for CPU usage compared to Multipoint Control Units (MCUs) that decode and mix video, making OpenVidu WebRTC suitable for large-scale broadcasts.
Mediasoup also supports advanced WebRTC features like Simulcast and Scalable Video Coding (SVC). These features allow the client to send multiple layers of video quality, and the server dynamically switches the layer it forwards to each subscriber based on their available bandwidth and screen size. This ensures that a participant on a slow 3G network receives a low-resolution stream, while a participant on fiber receives the high-definition stream, all originating from a single publish operation.
Key Features That Differentiate OpenVidu WebRTC
OpenVidu WebRTC stands out by offering a robust set of features that cover most real-time communication needs. It supports ultra-low latency live streaming, keeping end-to-end delay under 300 milliseconds, which is critical for interactive experiences. Developers can easily enable screen sharing, session recording, and virtual backgrounds through the SDK. The platform also supports advanced capabilities like AI agent integration and SIP telephony support, bridging traditional phone lines with WebRTC sessions.
Security is a priority, with token-based authentication ensuring only authorized users access sessions, alongside options for End-to-End Encryption (E2EE) to protect media payloads. The breadth of multi-platform SDKs means you can deploy a consistent video experience across web, mobile, and even Unity environments. For developers looking to build similar features with a managed approach, VideoSDK's video calling API offers a comparable feature set without the infrastructure overhead. VideoSDK also provides a Prebuilt UI Kit for zero-code embedding, a feature that OpenVidu lacks natively, requiring developers to build their own user interfaces from scratch.
Setting Up an OpenVidu WebRTC Deployment
Deploying OpenVidu WebRTC requires a server with Docker installed, adequate CPU resources, and a public IP address with a domain name configured for TLS. The recommended way to deploy OpenVidu is using their official Docker image, which bundles the OpenVidu Server and Mediasoup. You begin by pulling the Docker image from the official repository. Next, you configure the environment variables, specifically setting a strong secret key that the server uses to generate tokens.
You also need to expose the necessary ports for both signaling and media traffic, ensuring your firewall allows UDP traffic for the WebRTC media streams. Finally, you start the container, and the platform handles the rest, including automatic certificate provisioning via Let's Encrypt if you configured a domain name. For production deployments, you should consider placing the OpenVidu server behind a load balancer and configuring a dedicated TURN server to handle participants on restrictive networks. Managing a self-hosted WebRTC infrastructure requires ongoing DevOps effort to ensure high availability and security patching.

Building a Simple Video Call with the OpenVidu Browser SDK
Creating a video call application with the OpenVidu Browser SDK involves a few logical steps. First, you initialize the OpenVidu object in your frontend application. You then create a session object, which represents the video room. To join the session, you pass the token generated by your backend server. Once connected, you can publish your own camera and microphone stream to the session. The SDK handles device permissions, prompting the user for camera and microphone access.
It is crucial to implement proper error handling here, as users often deny permissions or have hardware issues. You can also enable screen sharing by specifying a different media source when publishing. To record the session, you simply trigger the recording method on the server side, and OpenVidu saves the composite video file to your configured storage. Managing the participant layout requires you to listen for stream creation events and dynamically attach the incoming media streams to video elements in your DOM. This publisher-subscriber model gives you fine-grained control over the video experience but requires significant frontend development effort to create a polished user interface.
Real-World Use Cases for OpenVidu WebRTC
OpenVidu WebRTC is used across various industries. In telehealth, it powers secure patient-doctor consultations where data privacy is paramount. Online education platforms use it to build interactive virtual classrooms with screen sharing and breakout rooms. Live-shopping events leverage its low-latency streaming to create real-time engagement between hosts and viewers. Even specialized applications like drone video feeds rely on OpenVidu to stream high-quality video from remote locations.
A common scenario involves a company migrating from a SaaS video provider to OpenVidu to cut costs and maintain full control over their user data, ensuring compliance with strict regional data protection regulations. Another example is a legal tech startup that uses OpenVidu to conduct virtual depositions, requiring absolute certainty that video data never passes through third-party servers. These use cases highlight the platform's strength in scenarios where data sovereignty and cost predictability are more important than the convenience of a managed service.
Comparing OpenVidu WebRTC with Popular Alternatives
When evaluating OpenVidu WebRTC against alternatives like Twilio Video, Agora, Daily.co, and 100ms, the primary decision axis is self-hosting versus managed cloud. OpenVidu wins when you need complete control over your infrastructure, data privacy, and predictable costs without per-minute billing. However, managed solutions like VideoSDK or Agora win when you want to avoid infrastructure maintenance, need global edge networks for massive scale, or require rapid deployment.
VideoSDK, for instance, provides a Prebuilt UI Kit and handles all the WebRTC heavy lifting, allowing developers to ship video calls in minutes without managing Docker containers or TURN servers. According to the W3C WebRTC specification, building a compliant WebRTC stack is complex, which is why many developers opt for managed platforms. OpenVidu requires a dedicated DevOps effort to maintain, whereas VideoSDK offers a free tier and handles scaling automatically.
| Feature | OpenVidu WebRTC | Twilio Video | Agora | VideoSDK |
|---|---|---|---|---|
| Hosting Model | Self-hosted | Managed Cloud | Managed Cloud | Managed Cloud |
| Latency | Ultra-low (<300ms) | Low | Low | Low (<300ms) |
| Pricing | Free (Open Source) | Per-minute | Per-minute | Free tier + prepaid |
| SDK Breadth | JS, React, iOS, Android, Unity | Multiple | Multiple | 10+ platforms |
| Best For | Data privacy, full control | Quick SaaS setup | Massive global scale | Rapid deployment, custom UI |
Troubleshooting Common Issues
Developers deploying OpenVidu WebRTC often encounter a few common issues. Browser compatibility can be tricky, as different browsers handle WebRTC APIs differently. Token expiration is another frequent problem, requiring your backend to generate fresh tokens for new sessions. TURN connectivity failures usually occur if the firewall blocks UDP ports, preventing participants behind strict NATs from connecting. High CPU usage during recording can happen if the server lacks sufficient resources.
A quick checklist for developers includes verifying that all required ports are open, ensuring the domain TLS certificates are valid, and checking that the OpenVidu secret key matches between the client and server configurations. If participants cannot see each other, checking the browser console for ICE connection failures is the first step. Additionally, ensuring that your server's firewall allows traffic on the UDP port range specified in your OpenVidu configuration is critical for establishing media flows.
Definitions Glossary
OpenVidu Server: The backend component that manages sessions, tokens, and signaling for the WebRTC platform.
Mediasoup: A WebRTC Selective Forwarding Unit (SFU) used by OpenVidu to route media streams efficiently.
Session: A virtual room in OpenVidu where participants connect to share audio and video.
TURN Server: A relay server used in WebRTC to bypass symmetric NATs and firewalls when direct peer connections fail.
WebRTC: An open-source project that enables real-time communication of audio, video, and data in web browsers and mobile apps.
Key Takeaways
- OpenVidu WebRTC is a powerful open-source platform for building real-time video applications with full control over your infrastructure.
- The architecture relies on an OpenVidu Server for signaling and Mediasoup for low-latency media routing.
- It supports essential features like screen sharing, recording, and multi-platform SDKs.
- Self-hosting OpenVidu is ideal for data privacy and cost predictability, while managed solutions like VideoSDK offer faster deployment and zero maintenance.
- Troubleshooting WebRTC applications requires careful attention to firewall rules, TURN servers, and token management.
Conclusion
OpenVidu WebRTC is a compelling choice for developers who need granular control over their real-time communication infrastructure, offering a robust, open-source alternative to managed SaaS platforms. By leveraging Mediasoup for media routing, it delivers the ultra-low latency performance required for interactive video experiences. If you prefer to focus on building features rather than managing Docker containers and TURN servers, consider exploring VideoSDK's video calling API for a fully managed, scalable solution. What are you building with WebRTC? Drop a comment below, and check out the VideoSDK community on Discord to connect with other developers.
Step 5: Implementing Participant View
Managing Participants
The participant view is crucial for displaying the video streams of all users in the session. This step involves managing the addition and removal of participant video streams dynamically as users join and leave the session.
Displaying Video Streams of Multiple Participants
Handling Stream Events
We will update the
initializeSession function to handle participant events such as stream creation and destruction.JavaScript
1 function initializeSession(username) {
2 const OV = new OpenVidu();
3 const session = OV.initSession();
4
5 // Handle stream creation (when a new participant joins)
6 session.on('streamCreated', (event) => {
7 const subscriber = session.subscribe(event.stream, 'remote-videos');
8 subscriber.on('videoElementCreated', (event) => {
9 event.element.play();
10 const videoBox = document.createElement('div');
11 videoBox.className = 'video-box';
12 videoBox.id = `participant-${event.stream.streamId}`;
13 videoBox.appendChild(event.element);
14 document.getElementById('remote-videos').appendChild(videoBox);
15 });
16 });
17
18 // Handle stream destruction (when a participant leaves)
19 session.on('streamDestroyed', (event) => {
20 const videoBox = document.getElementById(`participant-${event.stream.streamId}`);
21 if (videoBox) {
22 videoBox.parentNode.removeChild(videoBox);
23 }
24 });
25
26 getToken().then(token => {
27 session.connect(token, { clientData: username })
28 .then(() => {
29 // Create a publisher for the local video
30 const publisher = OV.initPublisher('local-video', {
31 audioSource: undefined,
32 videoSource: undefined,
33 publishAudio: true,
34 publishVideo: true,
35 resolution: '640x480',
36 frameRate: 30,
37 insertMode: 'APPEND',
38 mirror: false
39 });
40 session.publish(publisher);
41
42 // Add event listeners for control buttons
43 document.getElementById('mute-audio').addEventListener('click', () => {
44 publisher.publishAudio(!publisher.stream.audioActive);
45 document.getElementById('mute-audio').textContent = publisher.stream.audioActive ? 'Mute Audio' : 'Unmute Audio';
46 });
47
48 document.getElementById('disable-video').addEventListener('click', () => {
49 publisher.publishVideo(!publisher.stream.videoActive);
50 document.getElementById('disable-video').textContent = publisher.stream.videoActive ? 'Disable Video' : 'Enable Video';
51 });
52
53 document.getElementById('share-screen').addEventListener('click', () => {
54 shareScreen(session, publisher);
55 });
56 })
57 .catch(error => {
58 console.error('Error connecting to the session:', error);
59 });
60 });
61
62 function getToken() {
63 return fetch('/api/get-token')
64 .then(response => response.json())
65 .then(data => data.token);
66 }
67
68 function shareScreen(session, publisher) {
69 OV.initPublisherAsync('local-video', {
70 videoSource: 'screen'
71 }).then(screenPublisher => {
72 session.unpublish(publisher);
73 session.publish(screenPublisher);
74
75 screenPublisher.on('streamDestroyed', () => {
76 session.unpublish(screenPublisher);
77 session.publish(publisher);
78 document.getElementById('share-screen').textContent = 'Share Screen';
79 });
80
81 document.getElementById('share-screen').textContent = 'Stop Sharing';
82 }).catch(error => {
83 console.error('Error sharing screen: ', error);
84 });
85 }
86 }
87Handling Participant Events
Stream Created
When a new participant joins the session, the
streamCreated event is triggered. This event allows us to subscribe to the new participant's stream and add their video element to the remote-videos container.Stream Destroyed
When a participant leaves the session, the
streamDestroyed event is triggered. This event removes the participant's video element from the remote-videos container.Code Examples for Managing Participant Views
The following JavaScript code ensures that participant video streams are dynamically added and removed as users join and leave the session:
Stream Creation Handling
Adds a new video element for each participant who joins the session.
JavaScript
1 session.on('streamCreated', (event) => {
2 const subscriber = session.subscribe(event.stream, 'remote-videos');
3 subscriber.on('videoElementCreated', (event) => {
4 event.element.play();
5 const videoBox = document.createElement('div');
6 videoBox.className = 'video-box';
7 videoBox.id = `participant-${event.stream.streamId}`;
8 videoBox.appendChild(event.element);
9 document.getElementById('remote-videos').appendChild(videoBox);
10 });
11 });
12Stream Destruction Handling
Removes the video element of the participant who leaves the session.
JavaScript
1 session.on('streamDestroyed', (event) => {
2 const videoBox = document.getElementById(`participant-${event.stream.streamId}`);
3 if (videoBox) {
4 videoBox.parentNode.removeChild(videoBox);
5 }
6 });
7By implementing the participant view, your OpenVidu application can now dynamically manage the video streams of all participants in the session. This functionality is essential for creating a seamless and interactive video conferencing experience.
In the next part, we will focus on running your code and testing the application to ensure everything works as expected. This will involve starting the OpenVidu server, launching the application in a browser, and performing some basic tests.
Step 6: Running Your Code and Conclusion
Now that we have implemented the core functionalities of our OpenVidu application, it's time to run the code and test the application to ensure everything works as expected. Follow these steps to start the OpenVidu server, launch the application, and perform some basic tests.
Starting the OpenVidu Server
Download and Launch OpenVidu Server
If you haven’t already, download the OpenVidu server from the OpenVidu Downloads page.
Start the server by running the following command in your terminal:
bash
1 ./openvidu start
2Configure OpenVidu
Ensure you have set the necessary configuration options, such as
OPENVIDU_SECRET and OPENVIDU_PUBLICURL, in your docker-compose.yml or environment variables. This configuration ensures that your OpenVidu server is secure and accessible.Launching the Application in a Browser
Start Your Application
Navigate to your project directory and start your application server. If you’re using a Node.js server, the command will typically be:
bash
1 node server.js
2Open Your Browser
Open your preferred web browser and navigate to
http://localhost:YOUR_PORT. Replace YOUR_PORT with the port number your application server is running on (commonly 3000 or 5000).Testing and Debugging Tips
Join the Session
Enter your name in the join screen and click the “Join” button. Ensure that your video stream appears in the local video container and any other participants' video streams appear in the remote video container.
Test Controls
Test the mute/unmute audio, enable/disable video, and share screen functionalities by clicking the corresponding buttons. Verify that the video and audio states toggle correctly and that screen sharing works as expected.
Check Console for Errors
Open the browser’s developer console (usually accessible with
F12 or Ctrl+Shift+I) and check for any errors or warnings. Debugging information and error messages can help you identify and fix issues in your code.Conclusion
In this comprehensive guide, we build a video chat app with OpenVidu WebRTC using Javascript
from scratch. By following these instructions, and step by step guide you have learned how to set up your environment, wireframe components, implement a join screen, add video controls, and manage participant views. With your application running, you can now explore advanced features and customize your application further.
FAQ
