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 JS —
examples/vanilla/— Standalone HTML page using the bundled SDK via script tag - React —
examples/react/— Minimal React app usingwebrtc-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 modulewebrtc-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();
| Event | When |
|---|---|
| participant-joined, participant-left, participant-updated | Participant lifecycle |
| host-updated, rtc-session-ended | Session state |
| approval-pending, approval-requested, -approved, -rejected, -cancelled | Approval flow |
| video-track, audio-track, screen-track, video-track-removed | Remote tracks |
| screen-shared, screen-share-stopped, whiteboard-started, whiteboard-stopped | Media 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 = '/'}
/>
</>
);
}
| Component | Purpose |
|---|---|
| WebRTCSession | Meeting UI: grid, controls, chat |
| WebrtcPreload | Initializes signaling connection |
| ParticipantGrid, ParticipantBox, MediaControls | Layout and controls |
| StartMeeting, JoinMeeting | Start/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(); },
});
| Method | Description |
|---|---|
| initPreload(config) | Initialize client |
| initSession(config) | Mount meeting UI |
| init(config) | initPreload + initSession |
| destroyPreload, destroySession, destroyAll, getClient | Tear 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