Back
$cat ./low-latency-telephony-screensharing-websockets-docker.md

Building Low-Latency Real-Time Telephony & Screen Sharing: WebSockets, WebRTC & Docker

S
Surinder Singh•August 18, 2026•3 min read
CloudWebSocketsWebRTCDockerSystem Design
Building Low-Latency Real-Time Telephony & Screen Sharing: WebSockets, WebRTC & Docker

The Architecture of Real-Time Web Applications

Building interactive SaaS platforms like cloud telephony dialers (Dialmantra Dialer) and low-latency remote collaboration tools (Amotus Online) requires mastering real-time network protocols: WebSockets, WebRTC, and SIP over WebSockets (JsSIP).

Unlike traditional stateless HTTP APIs, real-time communications involve long-lived bidirectional channels, dynamic media stream negotiation (SDP/ICE), and resilient session reconnect handlers.


1. In-Browser VoIP Telephony with JsSIP & WebRTC

To eliminate expensive on-premise PBX hardware, we built browser-native VoIP calling portals directly in React using JsSIP communicating with cloud SIP gateways over secure WebSockets (wss://):

typescript
import { UA, WebSocketInterface } from 'jssip';

export function initializeSipUserAgent(extension: string, secret: string, serverWsUrl: string) {
  const socket = new WebSocketInterface(serverWsUrl);
  
  const configuration = {
    sockets: [socket],
    uri: `sip:${extension}@sip.dialmantra.in`,
    password: secret,
    session_timers: false,
    register: true,
  };

  const phoneUA = new UA(configuration);

  phoneUA.on('registered', () => {
    console.log(`[SIP] Extension ${extension} registered successfully.`);
  });

  phoneUA.on('newRTCSession', ({ session }) => {
    session.on('accepted', () => {
      const remoteStream = session.connection.getRemoteStreams()[0];
      const audioElement = document.getElementById('remote-audio') as HTMLAudioElement;
      if (audioElement && remoteStream) {
        audioElement.srcObject = remoteStream;
        audioElement.play();
      }
    });
  });

  phoneUA.start();
  return phoneUA;
}

2. Low-Latency Screen Sharing with WebRTC Media Streams

For real-time screen sharing and collaborative co-browsing, WebRTC peer-to-peer data channels and media tracks deliver sub-100ms video rendering:

typescript
// Screen Sharing Stream Capture
export async function startScreenShareSession(peerConnection: RTCPeerConnection) {
  try {
    const screenStream = await navigator.mediaDevices.getDisplayMedia({
      video: {
        frameRate: { ideal: 30, max: 60 },
        width: { ideal: 1920 },
        height: { ideal: 1080 },
      },
      audio: true,
    });

    // Replace video track on active peer connection
    const videoTrack = screenStream.getVideoTracks()[0];
    const sender = peerConnection.getSenders().find((s) => s.track?.kind === 'video');
    
    if (sender) {
      sender.replaceTrack(videoTrack);
    } else {
      peerConnection.addTrack(videoTrack, screenStream);
    }
  } catch (error) {
    console.error('Failed to acquire screen stream:', error);
  }
}

3. Stateful Cloud Deployment with Docker & Sticky Sessions

Because WebSocket and WebRTC signaling sessions maintain in-memory state, deploying them across cloud clusters requires:

  1. Sticky Session Load Balancing: Nginx or AWS ALB IP-hash routing to direct client reconnects to the same backend pod.
  2. Heartbeat & Backoff Reconnection: Implementing exponential jitter backoff on the frontend to gracefully handle cellular network handovers.
  3. Containerized Microservices: Dockerizing signaling daemons with high socket descriptor limits (ulimit -n 65535).

4. Key Performance Impact

  • 35% Reduction in Data Latency: Replacing polling with bidirectional WebSocket channels.
  • 50% Faster Customer Onboarding: Completely removed external softphones and hardware setup through in-browser JsSIP dialing.
Explore more articles→

Discussion (0)

Technical insights, critiques, and feedback

Verifying authentication status...

No comments yet. Be the first to start the discussion!