LiveKit Client SDK
The `livekit-client` package provides a JavaScript/TypeScript SDK for building real-time communication applications featuring video, audio, and data. It connects to LiveKit Cloud or self-hosted LiveKit servers, enabling developers to integrate functionalities like multi-modal AI, live streaming, and video calls. The current stable version is 2.18.3, with a release cadence featuring frequent patch updates and minor versions typically every one to two weeks. Key differentiators include its focus on performance optimizations like adaptive streaming and dynacast, robust event-driven architecture, and comprehensive support for various media types and advanced features like End-to-End Encryption (E2EE) and data tracks, offering a powerful platform for interactive media applications.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` syntax in an ECMAScript Module (ESM) context (e.g., in a modern React or Vue project without a proper build setup for CJS).fixReplace `const livekit = require('livekit-client');` with `import * as livekit from 'livekit-client';` or use named imports like `import { Room } from 'livekit-client';`. -
Failed to connect to room: Invalid token
cause The LiveKit access token provided is expired, malformed, or does not grant the necessary permissions for the requested room and participant identity.fixEnsure your token generation logic is correct, the token includes the required `RoomJoin` grant, and the token has not expired. Regenerate the token and verify server-side configuration. -
DOMException: Permission denied
cause The browser has denied access to the user's camera or microphone. This can be due to user choice, insecure context (non-HTTPS), or system-level permissions.fixEnsure your application is served over HTTPS. Prompt the user for media permissions and provide UI guidance. Check browser and operating system privacy settings for camera/microphone access. -
TypeError: livekit.Room is not a constructor
cause When using `require('livekit-client')` in CommonJS, if the module's export structure doesn't expose `Room` directly as a property, or if the global `LivekitClient` object is not available in a script tag setup.fixIf using CommonJS, ensure you are accessing `Room` correctly (e.g., `const livekit = require('livekit-client'); const room = new livekit.Room();`). If using a script tag, ensure the global `LivekitClient` object is loaded and use `new LivekitClient.Room()`.
Warnings
- breaking Migrating from v1.x to v2.x involves breaking changes. Consult the official migration guide for a detailed overview of what has changed.
- breaking The log context field `pID` was renamed to `participantID` for consistency and clarity in logging. This affects how participant identifiers appear in internal logs.
- gotcha Calling `room.prepareConnection(url, token)` as early as possible (e.g., when the page loads) can significantly speed up the actual `room.connect()` time by pre-warming WebRTC resources.
- gotcha End-to-End Encryption (E2EE) requires careful setup, including key management and server-side configuration, to ensure secure communication. Misconfiguration can lead to failed connections or unencrypted streams.
- gotcha LiveKit client v2.17.0 introduced a new default RTC path that uses a single peer connection mode, falling back to the legacy dual peer connection mode if necessary. This change aims to improve performance but might alter network behavior for some setups.
Install
-
npm install livekit-client -
yarn add livekit-client -
pnpm add livekit-client
Imports
- Room
const Room = require('livekit-client').Room;import { Room } from 'livekit-client'; - RoomEvent
const RoomEvent = require('livekit-client').RoomEvent;import { RoomEvent } from 'livekit-client'; - VideoPresets
const VideoPresets = require('livekit-client').VideoPresets;import { VideoPresets } from 'livekit-client';
Quickstart
import {
LocalParticipant,
LocalTrackPublication,
Participant,
RemoteParticipant,
RemoteTrack,
RemoteTrackPublication,
Room,
RoomEvent,
Track,
VideoPresets,
} from 'livekit-client';
async function setupLiveKitRoom() {
const url = process.env.LIVEKIT_URL ?? 'ws://localhost:7800'; // Replace with your LiveKit server URL
const token = process.env.LIVEKIT_TOKEN ?? 'YOUR_LIVEKIT_TOKEN'; // Replace with your LiveKit access token
if (token === 'YOUR_LIVEKIT_TOKEN') {
console.error('Please provide a LiveKit access token. You can generate one from your LiveKit server or dashboard.');
return;
}
const room = new Room({
adaptiveStream: true,
dynacast: true,
videoCaptureDefaults: {
resolution: VideoPresets.h720.resolution,
},
});
// Ensure a parent element exists to attach video/audio streams
const parentElement = document.getElementById('livekit-container') || document.body;
room.on(RoomEvent.TrackSubscribed, (track: RemoteTrack, publication: RemoteTrackPublication, participant: RemoteParticipant) => {
if (track.kind === Track.Kind.Video || track.kind === Track.Kind.Audio) {
const element = track.attach();
parentElement.appendChild(element);
console.log(`Track subscribed: ${track.kind} from ${participant.identity}`);
}
});
room.on(RoomEvent.TrackUnsubscribed, (track: RemoteTrack, publication: RemoteTrackPublication, participant: RemoteParticipant) => {
const element = track.detach();
element.remove();
console.log(`Track unsubscribed: ${track.kind} from ${participant.identity}`);
});
room.on(RoomEvent.ActiveSpeakersChanged, (speakers: Participant[]) => {
console.log('Active speakers:', speakers.map(s => s.identity));
});
room.on(RoomEvent.Disconnected, (reason: string | undefined) => {
console.log('Disconnected from room:', reason);
});
room.on(RoomEvent.LocalTrackUnpublished, (publication: LocalTrackPublication, participant: LocalParticipant) => {
console.log('Local track unpublished:', publication.trackSid);
});
console.log('Preparing connection...');
room.prepareConnection(url, token);
try {
await room.connect(url, token);
console.log('Connected to room:', room.name);
await room.localParticipant.enableCameraAndMicrophone();
console.log('Published local camera and microphone.');
} catch (error) {
console.error('Failed to connect to LiveKit room:', error);
}
}
// Call the setup function when the DOM is ready in a browser environment
if (typeof document !== 'undefined') {
document.addEventListener('DOMContentLoaded', setupLiveKitRoom);
} else {
// Fallback for non-browser environments or immediate execution
setupLiveKitRoom();
}