LiveKit
Add rtcstats-js to a LiveKit app with a singleton wrapper and three insertion points.
LiveKit's JavaScript SDK creates its peer connections through the browser's global RTCPeerConnection. rtcstats-js collects data by monkey-patching that same global. Patch once at startup, and every session LiveKit creates gets traced automatically - no forking, no internal hooks.
This guide shows how to add rtcstats-js to the livekit-client demo (examples/demo), but the pattern works in any LiveKit app.
Before you start
You need:
- A running
rtcstats-server(local or deployed) - A LiveKit app using
livekit-client(the demo works out of the box) - A signed rtcstats token (not the LiveKit token - these are separate auth systems)
Generate a token for local testing:
node bin/generate-token.js -u ws://localhost:8080/
This prints the full WebSocket URI with the token embedded. For production, mint tokens server-side. See the JWT-based authorization docs.
Step 1: install and create the singleton wrapper
npm install @rtcstats/rtcstats-js
Create a file (e.g. rtcstats.ts) that patches the globals once and exposes connect/close:
import { wrapRTCStatsWithDefaultOptions } from '@rtcstats/rtcstats-js';
type Trace = ReturnType<typeof wrapRTCStatsWithDefaultOptions>;
let trace: Trace | undefined;
export function initRTCStats(): Trace | undefined {
if (typeof window === 'undefined') return undefined;
if (!trace) {
trace = wrapRTCStatsWithDefaultOptions();
}
return trace;
}
export function connectRTCStats(url: string): void {
const t = initRTCStats();
if (t) t.connect(url);
}
export function closeRTCStats(): void {
trace?.close();
}
The if (!trace) guard prevents double-wrapping if the module is imported from multiple places.
Step 2: wire it into your LiveKit app
Three insertion points. The order matters.
At startup - patch globals before anything creates a peer connection:
import { closeRTCStats, connectRTCStats, initRTCStats } from './rtcstats';
initRTCStats();
const RTCSTATS_WS_URL = 'ws://localhost:8080/?rtcstats-token=<your-rtcstats-jwt>';
On connect - open a dump before prepareConnection (which prewarms a peer connection):
const room = new Room(roomOptions);
connectRTCStats(RTCSTATS_WS_URL);
await room.prepareConnection(url, token);
On disconnect - close the dump in your RoomEvent.Disconnected handler:
function handleRoomDisconnect(reason?: DisconnectReason) {
closeRTCStats();
// ... rest of your cleanup
}
One connectRTCStats call opens one dump file. One closeRTCStats call closes it. Everything in between is captured.
Verify it works
With rtcstats-server running, connect a LiveKit session. The server logs one accept on connect and one disconnect when the room closes:
Accepted new connection with uuid 93a750f8-223a-4c64-a39f-4c01f2731ae3
Connection with uuid 93a750f8-223a-4c64-a39f-4c01f2731ae3 disconnected, starting to process data
That pair confirms the dump opened and was processed. Your session data is now flowing to rtcstats-server.
NOTE: Can't get this to work? Need help? mailto:support@rtcstats.com
Was this page helpful?