Client SDK (webrtc-library)

Browser-side WebRTC client SDK for real-time communication. Connects to the signaling server provided by webrtc-server-library via Socket.IO.

Overview

This library handles:

  • WebRTC signaling — Exchanges SDP offers/answers and ICE candidates with the server
  • Peer lifecycle — Manages P2P RTCPeerConnection instances and participant state
  • P2P and SFU support — Peer-to-peer mode and SFU via Cloudflare
  • Media handling — getUserMedia, display capture, virtual backgrounds, device switching

The library runs in the browser. It uses Socket.IO for signaling and builds WebRTC connections based on server messages. Media flows peer-to-peer (or via SFU); the server does not handle media.

1. Using built-in meeting UI — React

Use React components to render the full meeting interface — participant grid, controls, chat, and more — with minimal setup.

import { WebrtcPreload, WebRTCSession } from 'webrtc-library/react';

// App root
<WebrtcPreload
  user={{ id: 'user-1', name: 'Alice' }}
  serverUrl="https://signaling.example.com"
  onClientReady={(client) => setClient(client)}
/>

// Meeting view
<WebRTCSession
  rtc_session={{ id: 'meeting-123', type: 'meeting' }}
  user={user}
  serverUrl="https://signaling.example.com"
  autoJoin={true}
  onLeave={() => navigate('/')}
/>

2. Using built-in meeting UI — Vanilla JS

Use the Vanilla JS SDK (script tag or bundled) for a framework-agnostic meeting UI without importing React.

// After loading Vanilla JS SDK bundle (script tag or bundled)
const instance = await window.Vidiomeet.init({
  container: '#meeting-root',
  serverUrl: 'https://signaling.example.com',
  user: { id: 'user-1', name: 'Alice' },
  rtc_session: { id: 'meeting-123', type: 'meeting' },
  autoJoin: true,
});
// instance.destroy() when done

3. Make your own UI

Use RTCSession directly to build a fully custom meeting experience. You handle events and attach tracks to your own elements.

import { RTCSession } from 'webrtc-library';

const user = { id: 'user-1', name: 'Alice', image: '/avatar.png' };
const session = new RTCSession(null, user, {
  signalingUrl: 'https://signaling.example.com',
});

session.on('participant-joined', ({ user }) => console.log('Joined:', user));
session.on('video-track', ({ userId, track }) => {
  document.getElementById('remote-video').srcObject = new MediaStream([track]);
});

session.id = 'meeting-123';
session.type = 'meeting';
await session.join();
// Call session.signalUIReady() once your UI is mounted

Examples

webrtc-library includes example apps for both Vanilla JS and React:

  • Vanilla JSexamples/vanilla/ — Standalone HTML page using the bundled SDK via script tag
  • Reactexamples/react/ — Minimal React app using webrtc-library/react

Run npm run build from the webrtc-library root, then serve the vanilla example or cd examples/react && npm install && npm run dev for the React example.

Package Exports

  • webrtc-library (default): Core module
  • webrtc-library/react: React components

Frontend SDK structure (webrtc-library)

In the downloaded SDK package, the frontend lives in webrtc-library/:

webrtc-library/
├── package.json          # exports: "." → client.es.js, "./react" → react/webrtc-react.es.js
├── client.es.js           # Core ESM: RTCSession, WebRTCClient
├── react/
│   └── webrtc-react.es.js # React: WebrtcPreload, WebRTCSession, ParticipantGrid, etc.
├── vanilla-js/            # UMD/IIFE bundles for script-tag use
│   ├── vanilla-sdk.umd.js
│   ├── vanilla-sdk.iife.js
│   └── vanilla-sdk.css
├── virtual-backgrounds/   # Assets for virtual backgrounds
└── examples/react/        # Built React example (reference)

Use client.es.js and react/webrtc-react.es.js with a bundler (Vite, webpack); use vanilla-js/ when you load the SDK via a script tag without a build step.

RTCSession

Core session handler. Advanced / low-level — prefer the React components or Vanilla JS SDK for most integrations.

Constructor: new RTCSession(socket, user, options) — socket (Socket.IO or null), user ({ id, name?, image? }), options (see configuration).

Main methods: init(), join(), leave(), end(), toggleAudio(), toggleVideo(), shareScreen(), startWhiteboard(), switchDevice(), approveUser(), rejectUser(), on(event, handler), off(event, handler), signalUIReady().

Event System

RTCSession emits events via on(event, handler). Call signalUIReady() once your UI is mounted so buffered events are replayed.

import { RTCSession } from 'webrtc-library';

const user = { id: 'user-1', name: 'Alice' };
const session = new RTCSession(null, user, { signalingUrl: 'https://signaling.example.com' });

// Subscribe to events
session.on('participant-joined', ({ user }) => {
  console.log('Participant joined:', user.name);
});

session.on('participant-left', ({ userId }) => {
  console.log('Participant left:', userId);
});

session.on('video-track', ({ userId, track }) => {
  const video = document.createElement('video');
  video.srcObject = new MediaStream([track]);
  video.autoplay = true;
  video.setAttribute('data-user-id', userId);
  document.getElementById('remote-videos').appendChild(video);
});

session.on('rtc-session-ended', () => {
  console.log('Meeting ended');
  window.location.href = '/';
});

// Join and signal UI ready so buffered events are replayed
session.id = 'meeting-123';
session.type = 'meeting';
await session.join();
session.signalUIReady();
EventWhen
participant-joined, participant-left, participant-updatedParticipant lifecycle
host-updated, rtc-session-endedSession state
approval-pending, approval-requested, -approved, -rejected, -cancelledApproval flow
video-track, audio-track, screen-track, video-track-removedRemote tracks
screen-shared, screen-share-stopped, whiteboard-started, whiteboard-stoppedMedia lifecycle

React Integration

Export path: webrtc-library/react. Use WebrtcPreload at app root; use WebRTCSession to render the meeting view.

import { WebrtcPreload, WebRTCSession } from 'webrtc-library/react';

function App() {
  return (
    <>
      <WebrtcPreload
        user={{ id: 'user-1', name: 'Alice' }}
        serverUrl="https://signaling.example.com"
        onClientReady={(client) => console.log('Client ready', client)}
      />
      <WebRTCSession
        rtc_session={{ id: 'meeting-123', type: 'meeting' }}
        user={{ id: 'user-1', name: 'Alice' }}
        serverUrl="https://signaling.example.com"
        autoJoin={true}
        onLeave={() => window.location.href = '/'}
      />
    </>
  );
}
ComponentPurpose
WebRTCSessionMeeting UI: grid, controls, chat
WebrtcPreloadInitializes signaling connection
ParticipantGrid, ParticipantBox, MediaControlsLayout and controls
StartMeeting, JoinMeetingStart/join meeting UI

Vanilla JS SDK (Bundled)

Convenience wrapper. Exposed as window.Vidiomeet when using the built SDK bundle.

// Option 1: init() — preload + session in one call
const instance = await window.Vidiomeet.init({
  container: '#meeting-root',
  serverUrl: 'https://signaling.example.com',
  user: { id: 'user-1', name: 'Alice' },
  rtc_session: { id: 'meeting-123', type: 'meeting' },
  autoJoin: true,
  onLeave: () => { /* cleanup */ },
});
// instance.destroy() when done

// Option 2: initPreload + initSession (separate control)
const preload = await window.Vidiomeet.initPreload({
  user: { id: 'user-1', name: 'Alice' },
  serverUrl: 'https://signaling.example.com',
  onClientReady: (client) => console.log('Client ready', client),
});
const session = window.Vidiomeet.initSession({
  container: '#meeting-root',
  user: { id: 'user-1', name: 'Alice' },
  serverUrl: 'https://signaling.example.com',
  client: preload.client,
  rtc_session: { id: 'meeting-123', type: 'meeting' },
  autoJoin: true,
  onLeave: () => { session.destroy(); preload.destroy(); },
});
MethodDescription
initPreload(config)Initialize client
initSession(config)Mount meeting UI
init(config)initPreload + initSession
destroyPreload, destroySession, destroyAll, getClientTear down / get instance

Configuration

RTCSession options: signalingUrl, socketOptions, rtcConfig (e.g. iceServers), bandwidthProfile (best | balanced | data-saver), userMediaConstraints, displayMediaConstraints.

ICE servers: Default stun:stun.l.google.com:19302. Add TURN via options.rtcConfig.iceServers.

Production Notes

  • getUserMedia and WebRTC generally require HTTPS (or localhost)
  • Chrome, Firefox, Safari, Edge with WebRTC support
  • No built-in TURN fallback; add via rtcConfig.iceServers
  • Virtual backgrounds use MediaPipe; performance varies by device