Understanding WebRTC: Building a Real-Time Interactive Portal

A comprehensive guide to WebRTC implementation, including peer-to-peer video calls, screen sharing, and collaborative features

by Rahul Vishwakarma

Real Time Interactive Portal

This guide explores how to build a peer-to-peer collaborative application using WebRTC, complete with video sharing, screen sharing, messaging, and file transfer capabilities.

Live Demo

Key Features

  • Peer-to-peer collaborative application with video sharing, screen sharing, messaging, and file transfer
  • Synchronized YouTube video playback across multiple tabs
  • Integrated code editor with peer-to-peer video call functionality (perfect for technical interviews)
  • Multi-language code editor support (C, C++, Java, Python, JavaScript/TypeScript, Golang, and more)

Technology Stack

Frontend

  • ReactJS with TailwindCSS for UI
  • WebRTC for peer-to-peer communication
  • Monaco editor for code editing
  • Yjs for collaborative editing features
  • Socket.io client for signaling

Backend

  • NodeJS with Express
  • Socket.io for signaling server implementation

Understanding WebRTC

WebRTC (Web Real-Time Communication) enables powerful peer-to-peer video and voice communication directly in the browser. Let’s dive into the key concepts and components.

WebRTC Architecture

WebRTC uses SRTP (Secure Real-time Transport Protocol) for encrypting, authenticating, and protecting data and conversations.

WebRTC Architecture

Connection Types

  1. P2P (Peer-to-Peer)

    • Ideal for 1:1 connections
    • Limited scalability due to connection overhead
  2. Mesh

    • Supports multiple connections (1:Many)
    • Resource-intensive for many connections
    • High CPU and bandwidth requirements
    • Limited scalability

Mesh Architecture

  1. SFU (Selective Forwarding Unit)
    • More efficient than mesh for multiple participants
    • Only requires sending/receiving media from each party once
    • Better scalability for larger groups

SFU Architecture

  1. MCU (Multipoint Control Unit)
    • Centralized processing unit
    • Handles media mixing and distribution

MCU Architecture

Essential WebRTC Concepts

ICE (Interactive Connectivity Establishment)

ICE is a framework that allows browsers to connect with peers, overcoming challenges posed by firewalls and NAT:

const peerConnection = new RTCPeerConnection({
    iceServers: [{
        urls: "stun:stun.l.google.com:19302",
    }]
});

STUN and TURN Servers

STUN (Session Traversal Utilities for NAT)

  • Helps discover public IP addresses
  • Determines router restrictions

TURN (Traversal Using Relays around NAT)

  • Enhanced version of STUN
  • Provides relay services when direct connection fails
const iceConfiguration = {
    iceServers: [
        {
            urls: 'turn:my-turn-server.mycompany.com:19403',
            username: 'optional-username',
            credential: 'auth-token'
        }
    ]
};

NAT (Network Address Translation)

NAT enables private networks to interact with the internet by translating private IP addresses to public ones. This process is crucial for:

  • Managing private network addressing
  • Enabling internet connectivity for multiple devices
  • Providing security through address translation

SDP (Session Description Protocol)

SDP describes multimedia content of the connection:

  • Resolution specifications
  • Format details
  • Codec information
  • Encryption parameters

Implementation Guide

1. Setting Up Media Access

// Access camera and microphone
window.navigator.mediaDevices.getUserMedia({ 
    video: true, 
    audio: true 
}).then((stream) => {
    setLocalStream(stream);
});

// Enable screen sharing
const screenStream = await window.navigator.mediaDevices.getDisplayMedia({ 
    video: true 
});
const screenTrack = screenStream.getVideoTracks()[0];

2. Establishing Peer Connection

// Create and configure peer connection
const peerConnection = new RTCPeerConnection(iceConfiguration);

// Add media tracks
peerConnection.addTrack(localStream.getVideoTracks()[0]);

// Create and set offer
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

3. Implementing Screen Sharing

async function handleScreenShare() {
    if (!option.isScreenSharing) {
        try {
            const screenStream = await window.navigator.mediaDevices.getDisplayMedia({ 
                video: true 
            });
            const screenTrack = screenStream.getVideoTracks()[0];

            // Replace video track
            const senders = peerConnection.getSenders();
            const videoSender = senders.find(sender => 
                sender.track.kind === 'video'
            );
            videoSender.replaceTrack(screenTrack);

            setLocalStream(screenStream);
            setOption((s) => ({ ...s, isScreenSharing: true }));

            screenTrack.onended = () => {
                handleStopScreenShare();
            };
        } catch (err) {
            console.error("Error sharing screen: ", err);
        }
    } else {
        handleStopScreenShare();
    }
}

4. Data Channel Implementation

const channel = peerConnection.createDataChannel('sendMessage');

channel.onopen = () => {
    console.log('Data channel is open');
    setOption((s) => ({ ...s, disabled: false }));
};

channel.onclose = () => {
    console.log('Data channel is closed');
    setOption((s) => ({ ...s, disabled: true }));
};

channel.onmessage = handleReceiveMessage;

5. Video Recording

async function RecordWindow() {
    const recordedChunks = [];
    const options = { mimeType: "video/webm; codecs=vp9" };
    
    const mediaRecorder = new MediaRecorder(
        recordOption === 'localStream' ? localStream : remoteStream, 
        options
    );
    
    mediaRecorder.ondataavailable = handleDataAvailable;
    mediaRecorder.start();
    
    function handleDataAvailable(e) {
        if (e.data.size > 0) {
            recordedChunks.push(e.data);
            download();
        }
    }
    
    function download() {
        const blob = new Blob(recordedChunks, {
            type: "video/webm",
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        document.body.appendChild(a);
        a.style = "display: none";
        a.href = url;
        a.download = "recording.webm";
        a.click();
        window.URL.revokeObjectURL(url);
    }
}

Debugging

For debugging WebRTC connections, you can use Chrome’s built-in WebRTC internals:

  • Open chrome://webrtc-internals/ in your Chrome browser
  • Monitor connection statistics, ICE candidates, and media metrics

Conclusion

WebRTC provides a powerful foundation for building real-time communication applications. By understanding its core concepts and implementing proper connection handling, you can create robust peer-to-peer applications with features like video calls, screen sharing, and file transfer.

For the complete source code and more details, visit the project repository.