### Run the Example Source: https://github.com/livekit/node-sdks/blob/main/examples/data-streams/README.md Execute this command to start the DataStreams example. ```bash pnpm run start ``` -------------------------------- ### Install Dependencies Source: https://github.com/livekit/node-sdks/blob/main/examples/data-streams/README.md Run this command to install the necessary dependencies for the example. ```bash pnpm install ``` -------------------------------- ### Install livekit-server-sdk Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Install the SDK using your preferred package manager. ```bash pnpm add livekit-server-sdk ``` ```bash yarn add livekit-server-sdk ``` ```bash npm install livekit-server-sdk --save ``` -------------------------------- ### Build All Packages in Monorepo with pnpm Source: https://github.com/livekit/node-sdks/blob/main/README.md Build all packages within the monorepo, including those in `/packages` and `/examples`. This is useful for initial setup and verifying installations. ```shell pnpm build ``` -------------------------------- ### Install Git Submodules Source: https://github.com/livekit/node-sdks/blob/main/README.md Run this command to install submodules. Ensure you run `pnpm build` afterwards. ```shell git submodule update --init --recursive ``` -------------------------------- ### Start Room Composite Egress Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Demonstrates how to start a Room Composite Egress using the updated v2 syntax. It shows the instantiation of `EncodedFileOutput` with an explicit `case` for the output type (e.g., 's3'). ```APIDOC ## startRoomCompositeEgress ### Description Starts a Room Composite Egress, which captures the entire room view as a composite stream. ### Method `egressClient.startRoomCompositeEgress(roomName, egressOptions)` ### Parameters #### Path Parameters - **roomName** (string) - Required - The name of the room to egress. #### Request Body - **egressOptions** (object) - Required - Options for the egress request. - **file** (EncodedFileOutput) - Required - Configuration for file output. - **filepath** (string) - Required - The desired path for the output file. - **output** (object) - Required - Specifies the output destination and format. - **case** (string) - Required - The type of output (e.g., 's3', 'gcs', 'azure'). - **value** (object) - Required - The specific configuration for the chosen output type. - **s3** (S3Upload) - Configuration for S3 upload. - **accessKey** (string) - Required - AWS access key. - **secret** (string) - Required - AWS secret key. - **bucket** (string) - Required - S3 bucket name. - **gcs** (GCSUpload) - Configuration for GCS upload. - **azure** (AzureUpload) - Configuration for Azure upload. ### Request Example ```typescript const fileOutput = new EncodedFileOutput({ filepath: 'dz/davids-room-test.mp4', output: { case: 's3', value: new S3Upload({ accessKey: 'aws-access-key', secret: 'aws-access-secret', bucket: 'my-bucket', }), }, }); const info = await egressClient.startRoomCompositeEgress('my-room', { file: fileOutput, }); ``` ### Response #### Success Response (200) - **info** (object) - Information about the started egress process. ``` -------------------------------- ### Start Room Composite Egress (v2) Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Use this snippet to start a Room Composite Egress with updated v2 syntax. Note the use of classes and the explicit 'case' field for the output type. ```typescript const fileOutput = new EncodedFileOutput({ filepath: 'dz/davids-room-test.mp4', output: { case: 's3', value: new S3Upload({ accessKey: 'aws-access-key', secret: 'aws-access-secret', bucket: 'my-bucket', }), }, }); const info = await egressClient.startRoomCompositeEgress('my-room', { file: fileOutput, }); ``` -------------------------------- ### Log Received Webhook Events in Next.js Source: https://github.com/livekit/node-sdks/blob/main/examples/webhooks-nextjs/README.md This example shows how to log incoming webhook events within your Next.js API route. It displays the received event data in the application logs. ```javascript received webhook event { event: 'participant_joined', ... } ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/livekit/node-sdks/blob/main/examples/data-streams/README.md Create a .env.local file and populate it with your LiveKit credentials and URL. ```bash LIVEKIT_API_KEY=your_api_key LIVEKIT_API_SECRET=your_api_secret LIVEKIT_URL=your_livekit_url ``` -------------------------------- ### Publishing Media and Data with LocalParticipant Source: https://context7.com/livekit/node-sdks/llms.txt Demonstrates how to publish audio and video tracks from various sources, send raw data messages, and unpublish tracks using the LocalParticipant. ```APIDOC ## Publish Audio Track from WAV File ### Description Publishes an audio track to the room from a WAV file after processing it into audio frames. ### Method `room.localParticipant.publishTrack(track, options)` ### Parameters - `track` (LocalAudioTrack): The audio track to publish. - `options` (TrackPublishOptions): Options for publishing the track, including source. ### Request Example ```typescript const audioSource = new AudioSource(16000, 1); const audioTrack = LocalAudioTrack.createAudioTrack('microphone', audioSource); const audioOptions = new TrackPublishOptions(); audioOptions.source = TrackSource.SOURCE_MICROPHONE; await room.localParticipant!.publishTrack(audioTrack, audioOptions); const wavBuffer = readFileSync('./audio.wav'); const pcm16 = new Int16Array(wavBuffer.buffer.slice(44)); const frame = new AudioFrame(pcm16, 16000, 1, pcm16.length); await audioSource.captureFrame(frame); ``` ## Publish Video Track (RGBA Frames) ### Description Publishes a video track to the room using RGBA frames captured from a video source. ### Method `room.localParticipant.publishTrack(track, options)` ### Parameters - `track` (LocalVideoTrack): The video track to publish. - `options` (TrackPublishOptions): Options for publishing the track, including source. ### Request Example ```typescript const videoSource = new VideoSource(1280, 720); const videoTrack = LocalVideoTrack.createVideoTrack('camera', videoSource); const videoOptions = new TrackPublishOptions(); videoOptions.source = TrackSource.SOURCE_CAMERA; await room.localParticipant!.publishTrack(videoTrack, videoOptions); const rgbaData = new Uint8Array(1280 * 720 * 4); const videoFrame = new VideoFrame(rgbaData, VideoBufferType.RGBA, 1280, 720); videoSource.captureFrame(videoFrame); ``` ## Send Raw Data ### Description Sends raw binary data to other participants in the room. ### Method `room.localParticipant.publishData(message, options)` ### Parameters - `message` (Uint8Array): The binary data to send. - `options` (object): Options for data publishing, including reliability and topic. - `reliable` (boolean): Whether the message should be sent reliably. - `topic` (string): The topic for the data message. Omit for broadcast. - `destination_identities` (string[]): Array of participant identities to send the data to. Omit for broadcast. ### Request Example ```typescript const message = new TextEncoder().encode(JSON.stringify({ action: 'ping', ts: Date.now() })); await room.localParticipant!.publishData(message, { reliable: true, topic: 'control', destination_identities: ['user-123'], }); ``` ## Unpublish a Track ### Description Stops publishing a previously published track and closes the track. ### Method `room.localParticipant.unpublishTrack(trackSid)` and `track.close()` ### Parameters - `trackSid` (string): The unique identifier of the track to unpublish. ### Request Example ```typescript await room.localParticipant!.unpublishTrack(audioTrack.sid!); await audioTrack.close(); ``` ``` -------------------------------- ### Publish an Audio Track Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-rtc/README.md Publishes an audio track to the connected room. It demonstrates setting up an audio source, creating a local audio track, and capturing audio frames. Note the recommendation to use `buffer.subarray` over `buffer.slice` for converting Uint8Array to Int16Array to avoid potential issues. ```typescript import { AudioFrame, AudioSource, LocalAudioTrack, TrackPublishOptions, TrackSource, } from '@livekit/rtc-node'; import { readFileSync } from 'node:fs'; // set up audio track const source = new AudioSource(16000, 1); const track = LocalAudioTrack.createAudioTrack('audio', source); const options = new TrackPublishOptions(); options.source = TrackSource.SOURCE_MICROPHONE; // note: if converting from Uint8Array to Int16Array, *do not* use buffer.slice! // it is marked unstable by Node and can cause undefined behaviour, such as massive chunks of // noise being added to the end. // it is recommended to use buffer.subarray instead. const sample = readFileSync(pathToFile); var buffer = new Int16Array(sample.buffer); await room.localParticipant.publishTrack(track, options); await source.captureFrame(new AudioFrame(buffer, 16000, 1, buffer.byteLength / 2)); // cleanup resources await track.close(); ``` -------------------------------- ### Creating Access Tokens Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Generate access tokens for participants to join LiveKit rooms. Tokens can be configured with specific permissions and have an optional expiration time. ```APIDOC ## AccessToken ### Description Creates an access token for a participant to join a LiveKit room. The token can be configured with various grants and an optional Time-To-Live (TTL). ### Method `new AccessToken(apiKey: string, apiSecret: string, options?: { identity: string, ttl?: number | string })` ### Method `addGrant(grant: { roomJoin: boolean, room: string, canPublish?: boolean, canSubscribe?: boolean })` ### Method `toJwt(): Promise` ### Example ```typescript import { AccessToken } from 'livekit-server-sdk'; const roomName = 'name-of-room'; const participantName = 'user-name'; const at = new AccessToken('api-key', 'secret-key', { identity: participantName, }); at.addGrant({ roomJoin: true, room: roomName }); const token = await at.toJwt(); console.log('access token', token); ``` ### Example with Permissions ```typescript const at = new AccessToken('api-key', 'secret-key', { identity: participantName, }); at.addGrant({ roomJoin: true, room: roomName, canPublish: false, canSubscribe: true, }); ``` ``` -------------------------------- ### IngressClient Source: https://context7.com/livekit/node-sdks/llms.txt Creates ingress endpoints that allow external sources (RTMP, WHIP, URL pull) to publish media into LiveKit rooms. ```APIDOC ## IngressClient ### Description Creates ingress endpoints that allow external sources (RTMP, WHIP, URL pull) to publish media into LiveKit rooms. ### Methods #### `createIngress(input: IngressInput, options: CreateIngressOptions)` Creates a new ingress endpoint. #### `listIngress(filter?: ListIngressRequest)` Lists existing ingress endpoints, optionally filtered by room name. #### `updateIngress(ingressId: string, options: UpdateIngressOptions)` Updates an existing ingress endpoint's configuration. #### `deleteIngress(ingressId: string)` Deletes an ingress endpoint. ### Request Example (Create RTMP Ingress) ```typescript import { IngressClient, IngressInput } from 'livekit-server-sdk'; const ingress = new IngressClient('wss://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); const rtmpIngress = await ingress.createIngress(IngressInput.RTMP_INPUT, { name: 'obs-stream', roomName: 'broadcast-room', participantIdentity: 'broadcaster-1', participantName: 'Main Stream', enableTranscoding: true, }); console.log('RTMP URL:', rtmpIngress.url); console.log('Stream Key:', rtmpIngress.streamKey); ``` ### Request Example (Create WHIP Ingress) ```typescript const whipIngress = await ingress.createIngress(IngressInput.WHIP_INPUT, { name: 'whip-source', roomName: 'broadcast-room', participantIdentity: 'whip-publisher', enableTranscoding: false, // passthrough for WHIP }); ``` ### Request Example (Create URL-Pull Ingress) ```typescript const urlIngress = await ingress.createIngress(IngressInput.URL_INPUT, { name: 'vod-replay', roomName: 'replay-room', participantIdentity: 'vod-source', url: 'https://example.com/video.mp4', }); ``` ### Request Example (List Ingresses) ```typescript const ingressList = await ingress.listIngress({ roomName: 'broadcast-room' }); ``` ### Request Example (Update Ingress) ```typescript await ingress.updateIngress(rtmpIngress.ingressId, { name: 'obs-stream-updated', participantName: 'Primary Stream', }); ``` ### Request Example (Delete Ingress) ```typescript await ingress.deleteIngress(rtmpIngress.ingressId); ``` ``` -------------------------------- ### Registering and Performing RPC Methods Source: https://context7.com/livekit/node-sdks/llms.txt Details on how to register custom RPC methods on the server/agent side and how to invoke these methods from a client participant. ```APIDOC ## Register RPC Method ### Description Registers a named RPC method that can be invoked by other participants. ### Method `room.localParticipant.registerRpcMethod(method, handler)` ### Parameters - `method` (string): The name of the RPC method. - `handler` (function): An asynchronous function that handles the RPC request. It receives `RpcInvocationData` and should return a string payload or throw an `RpcError`. - `data.callerIdentity` (string): The identity of the participant who invoked the method. - `data.payload` (string): The payload sent by the caller. ### Request Example ```typescript room.localParticipant!.registerRpcMethod( 'ai.generateSummary', async (data: RpcInvocationData): Promise => { console.log(`Request from ${data.callerIdentity}: ${data.payload}`); const { topic, maxWords } = JSON.parse(data.payload); if (!topic) { throw new RpcError(1001, 'topic is required'); } const summary = `Summary of "${topic}" in ${maxWords} words: ...`; return JSON.stringify({ summary, generatedAt: Date.now() }); }, ); ``` ## Perform RPC Call ### Description Invokes a registered RPC method on another participant. ### Method `room.localParticipant.performRpc(options)` ### Parameters - `options` (object): Configuration for the RPC call. - `destinationIdentity` (string): The identity of the participant to call. - `method` (string): The name of the RPC method to invoke. - `payload` (string): The data payload to send to the handler. - `responseTimeout` (number): The timeout in milliseconds for receiving a response. ### Request Example ```typescript try { const response = await room.localParticipant!.performRpc({ destinationIdentity: 'ai-agent', method: 'ai.generateSummary', payload: JSON.stringify({ topic: 'WebRTC', maxWords: 100 }), responseTimeout: 10_000, }); const result = JSON.parse(response); console.log('Summary:', result.summary); } catch (err) { if (err instanceof RpcError) { console.error(`RPC error ${err.code}: ${err.message}`); } } ``` ## Unregister RPC Method ### Description Unregisters a previously registered RPC method. ### Method `room.localParticipant.unregisterRpcMethod(method)` ### Parameters - `method` (string): The name of the RPC method to unregister. ### Request Example ```typescript room.localParticipant!.unregisterRpcMethod('ai.generateSummary'); ``` ``` -------------------------------- ### Send and Receive Data Streams in Node.js Source: https://context7.com/livekit/node-sdks/llms.txt Demonstrates sending text and binary data streams, and registering handlers to receive them. Use streaming writers for incremental updates and `sendFile` for binary data. Ensure handlers are registered before data is sent. ```typescript import { Room, RoomEvent } from '@livekit/rtc-node'; import type { TextStreamReader, ByteStreamReader } from '@livekit/rtc-node'; // ---- Sender: stream LLM output token by token ---- // Simple one-shot send await room.localParticipant!.sendText('Hello, world!', { topic: 'chat' }); // Streaming writer for incremental updates const textWriter = await room.localParticipant!.streamText({ topic: 'llm-output', attributes: { model: 'gpt-4o', sessionId: 'sess-123' }, destinationIdentities: ['user-456'], // omit to broadcast }); for (const token of ['Hello', ', ', 'this ', 'is ', 'streaming!']) { await textWriter.write(token); await new Promise((r) => setTimeout(r, 50)); // simulate streaming delay } await textWriter.close(); // ---- Sender: send a file as byte stream ---- await room.localParticipant!.sendFile('./report.pdf', { topic: 'file-transfer', mimeType: 'application/pdf', destinationIdentities: ['user-456'], }); // ---- Receiver: handle incoming text streams ---- room.registerTextStreamHandler('llm-output', async (reader: TextStreamReader, sender) => { console.log(`Receiving text stream from ${sender.identity}, topic: ${reader.info.topic}`); for await (const chunk of reader) { process.stdout.write(chunk); // incremental text output } console.log('\nStream complete'); }); // ---- Receiver: handle incoming byte streams ---- room.registerByteStreamHandler('file-transfer', async (reader: ByteStreamReader, sender) => { const { name, mimeType, totalSize } = reader.info; console.log(`Receiving file "${name}" (${mimeType}) from ${sender.identity}, size: ${totalSize}`); const chunks: Uint8Array[] = []; for await (const chunk of reader) { chunks.push(chunk); } const fileData = Buffer.concat(chunks); require('fs').writeFileSync(`./received-${name}`, fileData); }); // ---- Cleanup handlers ---- room.unregisterTextStreamHandler('llm-output'); room.unregisterByteStreamHandler('file-transfer'); ``` -------------------------------- ### Managing Rooms Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Use the `RoomServiceClient` to perform administrative operations on LiveKit rooms, such as listing, creating, and deleting them. ```APIDOC ## RoomServiceClient ### Description Provides APIs to manage LiveKit rooms. Requires API key and secret key for authentication. ### Constructor `new RoomServiceClient(livekitHost: string, apiKey: string, apiSecret: string)` ### Method `listRooms(): Promise` ### Description Retrieves a list of all active rooms in the LiveKit deployment. ### Method `createRoom(options: { name: string, emptyTimeout?: number, maxParticipants?: number }): Promise` ### Description Creates a new LiveKit room with specified options. ### Method `deleteRoom(roomName: string): Promise` ### Description Deletes a LiveKit room by its name. ### Example ```typescript import { Room, RoomServiceClient } from 'livekit-server-sdk'; const livekitHost = 'https://my.livekit.host'; const svc = new RoomServiceClient(livekitHost, 'api-key', 'secret-key'); // list rooms svc.listRooms().then((rooms: Room[]) => { console.log('existing rooms', rooms); }); // create a new room const opts = { name: 'myroom', emptyTimeout: 10 * 60, // 10 minutes maxParticipants: 20, }; sdc.createRoom(opts).then((room: Room) => { console.log('room created', room); }); // delete a room svc.deleteRoom('myroom').then(() => { console.log('room deleted'); }); ``` ``` -------------------------------- ### Connect to a LiveKit Room Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-rtc/README.md Connects to a LiveKit room and sets up event listeners for track subscriptions, disconnections, and local track publications. Ensure to disconnect and dispose of resources when the application exits. ```typescript import { RemoteParticipant, RemoteTrack, RemoteTrackPublication, Room, RoomEvent, dispose, } from '@livekit/rtc-node'; const room = new Room(); await room.connect(url, token, { autoSubscribe: true, dynacast: true }); console.log('connected to room', room); // add event listeners room .on(RoomEvent.TrackSubscribed, handleTrackSubscribed) .on(RoomEvent.Disconnected, handleDisconnected) .on(RoomEvent.LocalTrackPublished, handleLocalTrackPublished); process.on('SIGINT', () => { await room.disconnect(); await dispose(); }); ``` -------------------------------- ### RoomServiceClient — Manage rooms and participants Source: https://context7.com/livekit/node-sdks/llms.txt Provides client for server-side operations to manage LiveKit rooms, including creation, listing, deletion, and participant management. ```APIDOC ## RoomServiceClient — Manage rooms and participants ### Description `RoomServiceClient` provides CRUD operations for rooms and participant management including creating, listing, deleting rooms, and controlling participants and their tracks. ### Method Signature ```typescript new RoomServiceClient(url: string, apiKey: string, apiSecret: string) createRoom(options: CreateRoomRequest): Promise listRooms(roomNames?: string[]): Promise listParticipants(roomName: string): Promise getParticipant(roomName: string, identity: string): Promise updateParticipant(roomName: string, identity: string, updates: ParticipantUpdate): Promise mutePublishedTrack(roomName: string, identity: string, trackSid: string, mute: boolean): Promise sendData(roomName: string, payload: Uint8Array, kind: DataPacket_Kind, options?: SendDataOptions): Promise forwardParticipant(roomName: string, identity: string, targetRoom: string): Promise moveParticipant(roomName: string, identity: string, targetRoom: string): Promise removeParticipant(roomName: string, identity: string): Promise deleteRoom(roomName: string): Promise ``` ### Parameters #### RoomServiceClient constructor - **url** (string) - The URL of the LiveKit server. - **apiKey** (string) - Your LiveKit API key. - **apiSecret** (string) - Your LiveKit API secret. #### createRoom - **options** (CreateRoomRequest) - Configuration for the new room. - **name** (string) - The name of the room. - **emptyTimeout** (number) - Time in seconds before an empty room is closed. - **departureTimeout** (number) - Grace period in seconds after the last participant leaves. - **maxParticipants** (number) - Maximum number of participants allowed. - **metadata** (string) - Custom metadata as a JSON string. #### listRooms - **roomNames** (string[]) - Optional array of room names to filter the list. #### listParticipants - **roomName** (string) - The name of the room to list participants from. #### getParticipant - **roomName** (string) - The name of the room. - **identity** (string) - The identity of the participant. #### updateParticipant - **roomName** (string) - The name of the room. - **identity** (string) - The identity of the participant. - **updates** (ParticipantUpdate) - Object containing updates for the participant. - **metadata** (string) - Updated metadata as a JSON string. - **name** (string) - Updated display name. - **permission** (ParticipantPermission) - Updated permissions. - **canPublish** (boolean) - **canSubscribe** (boolean) - **canPublishData** (boolean) #### mutePublishedTrack - **roomName** (string) - The name of the room. - **identity** (string) - The identity of the participant. - **trackSid** (string) - The SID of the track to mute. - **mute** (boolean) - Whether to mute (true) or unmute (false) the track. #### sendData - **roomName** (string) - The name of the room. - **payload** (Uint8Array) - The data payload to send. - **kind** (DataPacket_Kind) - The kind of data packet (RELIABLE or LOSSY). - **options** (SendDataOptions) - Optional settings for sending data. - **topic** (string) - The topic for the data packet. - **destinationIdentities** (string[]) - Specific participant identities to send the data to. #### forwardParticipant - **roomName** (string) - The name of the source room. - **identity** (string) - The identity of the participant whose tracks to forward. - **targetRoom** (string) - The name of the destination room. #### moveParticipant - **roomName** (string) - The name of the source room. - **identity** (string) - The identity of the participant to move. - **targetRoom** (string) - The name of the destination room. #### removeParticipant - **roomName** (string) - The name of the room. - **identity** (string) - The identity of the participant to remove. #### deleteRoom - **roomName** (string) - The name of the room to delete. ### Response - **Room** (object) - Information about a room. - **Participant** (object) - Information about a participant. - **TrackInfo** (object) - Information about a media track. ### Request Example ```typescript import { RoomServiceClient, DataPacket_Kind } from 'livekit-server-sdk'; const svc = new RoomServiceClient('https://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); // Create a room with configuration const room = await svc.createRoom({ name: 'conference-room', emptyTimeout: 600, departureTimeout: 30, maxParticipants: 50, metadata: JSON.stringify({ type: 'webinar' }), }); console.log('created room:', room.name, room.sid); // List all rooms (or filter by name) const rooms = await svc.listRooms(['conference-room']); // List participants and get specific participant info const participants = await svc.listParticipants('conference-room'); const participant = await svc.getParticipant('conference-room', 'user-123'); console.log('tracks published:', participant.tracks.length); // Update participant permissions and metadata await svc.updateParticipant('conference-room', 'user-123', { metadata: JSON.stringify({ speaking: true }), name: 'Alice (host)', permission: { canPublish: true, canSubscribe: true, canPublishData: true }, }); // Mute a participant's track const trackInfo = await svc.mutePublishedTrack('conference-room', 'user-123', 'TR_xxxx', true); // Send server-side data to specific participants const payload = new TextEncoder().encode(JSON.stringify({ action: 'start-poll', pollId: '42' })); await svc.sendData('conference-room', payload, DataPacket_Kind.RELIABLE, { topic: 'poll-events', destinationIdentities: ['user-123', 'user-456'], }); // Forward a participant's tracks to another room await svc.forwardParticipant('conference-room', 'user-123', 'overflow-room'); // Move participant to a different room await svc.moveParticipant('conference-room', 'user-123', 'breakout-room-1'); // Remove a participant (they can still rejoin) await svc.removeParticipant('conference-room', 'bad-actor'); // Delete the room entirely await svc.deleteRoom('conference-room'); ``` ``` -------------------------------- ### Ingest External Media with IngressClient Source: https://context7.com/livekit/node-sdks/llms.txt Use IngressClient to create ingress endpoints for RTMP, WHIP, and URL pull sources to publish media into LiveKit rooms. Configure ingress settings like name, room, and participant details. ```typescript import { IngressClient, IngressInput } from 'livekit-server-sdk'; const ingress = new IngressClient('https://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); // Create an RTMP ingress for a live encoder (e.g. OBS) const rtmpIngress = await ingress.createIngress(IngressInput.RTMP_INPUT, { name: 'obs-stream', roomName: 'broadcast-room', participantIdentity: 'broadcaster-1', participantName: 'Main Stream', enableTranscoding: true, }); console.log('RTMP URL:', rtmpIngress.url); // rtmp://ingress.livekit.io/... console.log('Stream Key:', rtmpIngress.streamKey); // Create a WHIP ingress for WebRTC input const whipIngress = await ingress.createIngress(IngressInput.WHIP_INPUT, { name: 'whip-source', roomName: 'broadcast-room', participantIdentity: 'whip-publisher', enableTranscoding: false, // passthrough for WHIP }); // Create a URL-pull ingress to ingest an HLS/MP4 URL const urlIngress = await ingress.createIngress(IngressInput.URL_INPUT, { name: 'vod-replay', roomName: 'replay-room', participantIdentity: 'vod-source', url: 'https://example.com/video.mp4', }); // List ingresses, optionally filtered by room const ingressList = await ingress.listIngress({ roomName: 'broadcast-room' }); // Update an ingress configuration await ingress.updateIngress(rtmpIngress.ingressId, { name: 'obs-stream-updated', participantName: 'Primary Stream', }); // Delete an ingress await ingress.deleteIngress(rtmpIngress.ingressId); ``` -------------------------------- ### Create Access Token for Room Join Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Generate an access token for a participant to join a specified room. The room will be created automatically if it doesn't exist when the first client joins. The token can be configured with custom permissions. ```typescript import { AccessToken } from 'livekit-server-sdk'; // if this room doesn't exist, it'll be automatically created when the first // client joins const roomName = 'name-of-room'; // identifier to be used for participant. // it's available as LocalParticipant.identity with livekit-client SDK const participantName = 'user-name'; const at = new AccessToken('api-key', 'secret-key', { identity: participantName, }); at.addGrant({ roomJoin: true, room: roomName }); const token = await at.toJwt(); console.log('access token', token); ``` ```typescript const at = new AccessToken('api-key', 'secret-key', { identity: participantName, }); at.addGrant({ roomJoin: true, room: roomName, canPublish: false, canSubscribe: true, }); ``` -------------------------------- ### EgressClient Source: https://context7.com/livekit/node-sdks/llms.txt Controls egress pipelines for recording rooms to files, live-streaming to RTMP, and exporting individual participant tracks. ```APIDOC ## EgressClient ### Description Controls egress pipelines for recording rooms to files, live-streaming to RTMP, and exporting individual participant tracks. ### Methods #### `startRoomCompositeEgress(roomName: string, output: EncodedFileOutput | StreamOutput, options?: EgressOptions)` Starts an egress for a room composite. #### `updateStream(egressId: string, addUrls: string[], removeUrls: string[])` Adds or removes RTMP destinations from an active stream egress. #### `startParticipantEgress(roomName: string, participantId: string, output: EncodedFileOutput | StreamOutput, options?: ParticipantEgressOptions)` Starts an egress for a specific participant's tracks. #### `listEgress(filter?: ListEgressRequest)` Lists active egress pipelines for a room. #### `stopEgress(egressId: string)` Stops an active egress pipeline. ### Request Example (Start Room Composite Egress to S3) ```typescript import { EgressClient, EncodedFileOutput, S3Upload, EncodingOptionsPreset } from 'livekit-server-sdk'; const egress = new EgressClient('wss://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); const fileOutput = new EncodedFileOutput({ filepath: 'recordings/room-composite-{time}.mp4', output: { case: 's3', value: new S3Upload({ accessKey: process.env.AWS_ACCESS_KEY!, secret: process.env.AWS_SECRET_KEY!, region: 'us-east-1', bucket: 'my-recordings-bucket', }), }, }); const egressInfo = await egress.startRoomCompositeEgress('my-room', fileOutput, { layout: 'grid', encodingOptions: EncodingOptionsPreset.H264_1080P_30, }); console.log('egress started:', egressInfo.egressId); ``` ### Request Example (Start Room Composite Egress to RTMP) ```typescript import { EgressClient, StreamOutput, StreamProtocol } from 'livekit-server-sdk'; const egress = new EgressClient('wss://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); const streamOutput = new StreamOutput({ protocol: StreamProtocol.RTMP, urls: ['rtmps://live.twitch.tv/app/my-stream-key'], }); const streamEgress = await egress.startRoomCompositeEgress('my-room', streamOutput, { layout: 'speaker', audioOnly: false, }); ``` ### Request Example (Update Stream Egress) ```typescript await egress.updateStream(streamEgress.egressId, ['rtmps://a.rtmp.youtube.com/live2/my-key'], []); ``` ### Request Example (Start Participant Egress) ```typescript const participantEgress = await egress.startParticipantEgress( 'my-room', 'user-123', { file: fileOutput }, { screenShare: false }, ); ``` ### Request Example (List Egresses) ```typescript const activeEgresses = await egress.listEgress({ roomName: 'my-room', active: true }); ``` ### Request Example (Stop Egress) ```typescript await egress.stopEgress(egressInfo.egressId); ``` ``` -------------------------------- ### ConnectorClient Source: https://context7.com/livekit/node-sdks/llms.txt Bridges external communication platforms like WhatsApp and Twilio into LiveKit rooms. ```APIDOC ## ConnectorClient ### Description `ConnectorClient` bridges external communication platforms (WhatsApp Business API, Twilio) into LiveKit rooms. ### Methods #### dialWhatsAppCall Initiates an outbound WhatsApp call. - **Parameters** - `whatsappPhoneNumberId` (string) - Required - The WhatsApp Phone Number ID. - `whatsappToPhoneNumber` (string) - Required - The recipient's phone number. - `whatsappApiKey` (string) - Required - The WhatsApp API Key. - `whatsappCloudApiVersion` (string) - Required - The WhatsApp Cloud API version. - `roomName` (string) - Required - The name of the LiveKit room. - `participantIdentity` (string) - Required - The identity of the participant in the room. - `ringingTimeout` (number) - Optional - The timeout in seconds for the call to ring. ### connectTwilioCall Connects an inbound Twilio call to a room. - **Parameters** - `twilioCallDirection` (ConnectTwilioCallRequest_TwilioCallDirection) - Required - The direction of the Twilio call (INBOUND). - `roomName` (string) - Required - The name of the LiveKit room. - `participantIdentity` (string) - Required - The identity of the participant in the room. - `participantName` (string) - Optional - The name of the participant. ### disconnectWhatsAppCall Disconnects an active WhatsApp call. - **Parameters** - `callId` (string) - Required - The ID of the WhatsApp call to disconnect. - `whatsappApiKey` (string) - Required - The WhatsApp API Key. ``` -------------------------------- ### Control Egress Pipelines with EgressClient Source: https://context7.com/livekit/node-sdks/llms.txt Use EgressClient to manage recording rooms to files, live-streaming to RTMP, and exporting individual participant tracks. Ensure necessary imports and client initialization. ```typescript import { EgressClient, EncodedFileOutput, S3Upload, StreamOutput, StreamProtocol, EncodingOptionsPreset, } from 'livekit-server-sdk'; const egress = new EgressClient('https://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); // Record a room composite to S3 as MP4 const fileOutput = new EncodedFileOutput({ filepath: 'recordings/room-composite-{time}.mp4', output: { case: 's3', value: new S3Upload({ accessKey: process.env.AWS_ACCESS_KEY!, secret: process.env.AWS_SECRET_KEY!, region: 'us-east-1', bucket: 'my-recordings-bucket', }), }, }); const egressInfo = await egress.startRoomCompositeEgress('my-room', fileOutput, { layout: 'grid', encodingOptions: EncodingOptionsPreset.H264_1080P_30, }); console.log('egress started:', egressInfo.egressId); // Live-stream to RTMP const streamOutput = new StreamOutput({ protocol: StreamProtocol.RTMP, urls: ['rtmps://live.twitch.tv/app/my-stream-key'], }); const streamEgress = await egress.startRoomCompositeEgress('my-room', streamOutput, { layout: 'speaker', audioOnly: false, }); // Add an additional RTMP destination to an active stream await egress.updateStream(streamEgress.egressId, ['rtmps://a.rtmp.youtube.com/live2/my-key'], []); // Record a specific participant (their camera + mic) const participantEgress = await egress.startParticipantEgress( 'my-room', 'user-123', { file: fileOutput }, { screenShare: false }, ); // List active egresses for a room const activeEgresses = await egress.listEgress({ roomName: 'my-room', active: true }); // Stop an egress await egress.stopEgress(egressInfo.egressId); ``` -------------------------------- ### Manage SIP Trunks and Calls with SipClient Source: https://context7.com/livekit/node-sdks/llms.txt Use SipClient to create and manage SIP trunks for inbound and outbound calls. Programmatically initiate calls, route them to rooms, and transfer participants. ```typescript import { SipClient, SIPTransport } from 'livekit-server-sdk'; const sip = new SipClient('https://my-project.livekit.cloud', 'my-api-key', 'my-api-secret'); // Create an inbound SIP trunk (receives calls from PSTN) const inboundTrunk = await sip.createSipInboundTrunk('Support Line', ['+14155550100'], { allowedNumbers: ['+14155550200'], // optional DID filter authUsername: 'livekit-sip', authPassword: 'secret-password', krispEnabled: true, }); console.log('inbound trunk ID:', inboundTrunk.sipTrunkId); // Create an outbound SIP trunk (makes calls to PSTN) const outboundTrunk = await sip.createSipOutboundTrunk( 'Outbound Calls', 'sip.voip-provider.com:5060', ['+14155550100'], { transport: SIPTransport.SIP_TRANSPORT_TLS, authUsername: 'livekit', authPassword: 'secret', }, ); // Create a dispatch rule: route all calls from inbound trunk directly to a room const rule = await sip.createSipDispatchRule( { type: 'direct', roomName: 'support-queue', pin: '1234' }, { name: 'Support Queue Rule', trunkIds: [inboundTrunk.sipTrunkId] }, ); // Dial out to a phone number and add them to a room const sipParticipant = await sip.createSipParticipant( outboundTrunk.sipTrunkId, '+14155551234', 'my-room', { participantIdentity: 'caller-john', participantName: 'John Doe', playDialtone: true, waitUntilAnswered: true, maxCallDuration: 3600, // 1 hour max dtmf: '1w2w3', // press 1, wait 500ms, press 2, wait 500ms, press 3 }, ); console.log('SIP participant connected:', sipParticipant.participantIdentity); // Transfer a SIP participant to a different SIP URI await sip.transferSipParticipant('my-room', 'caller-john', 'sip:+14155559999@sip.provider.com', { playDialtone: true, ringingTimeout: 30, }); ``` -------------------------------- ### Configure LiveKit Server Webhooks Source: https://github.com/livekit/node-sdks/blob/main/examples/webhooks-nextjs/README.md Configure LiveKit server to send webhook events to your Next.js application. Ensure your API key and secret are correctly set. ```yaml webhook: urls: - http://localhost:3000/api/webhook api_key: ``` -------------------------------- ### Connect WhatsApp and Twilio Calls with ConnectorClient Source: https://context7.com/livekit/node-sdks/llms.txt Use ConnectorClient to bridge external communication platforms like WhatsApp and Twilio into LiveKit rooms. Requires LiveKit server URL, API key, and secret for initialization. ```typescript import { ConnectorClient, ConnectTwilioCallRequest_TwilioCallDirection } from 'livekit-server-sdk'; const connector = new ConnectorClient( 'https://my-project.livekit.cloud', 'my-api-key', 'my-api-secret', ); // Initiate an outbound WhatsApp call const whatsappCall = await connector.dialWhatsAppCall({ whatsappPhoneNumberId: '1234567890', whatsappToPhoneNumber: '+14155551234', whatsappApiKey: process.env.WHATSAPP_API_KEY!, whatsappCloudApiVersion: '23.0', roomName: 'support-room', participantIdentity: 'wa-customer', ringingTimeout: 30, }); console.log('WhatsApp call ID:', whatsappCall.whatsappCallId); // Connect an inbound Twilio call to a room (called from Twilio webhook handler) const twilioResult = await connector.connectTwilioCall({ twilioCallDirection: ConnectTwilioCallRequest_TwilioCallDirection.INBOUND, roomName: 'support-room', participantIdentity: 'twilio-caller', participantName: 'Incoming Call', }); console.log('Twilio WebSocket URL:', twilioResult.wsUrl); // use in TwiML // Disconnect an active WhatsApp call await connector.disconnectWhatsAppCall(whatsappCall.whatsappCallId, process.env.WHATSAPP_API_KEY!); ``` -------------------------------- ### Manage LiveKit Rooms Source: https://github.com/livekit/node-sdks/blob/main/packages/livekit-server-sdk/README.md Use RoomServiceClient to perform operations on rooms, such as listing, creating, and deleting them. Requires API key and secret for authentication. ```typescript import { Room, RoomServiceClient } from 'livekit-server-sdk'; const livekitHost = 'https://my.livekit.host'; const svc = new RoomServiceClient(livekitHost, 'api-key', 'secret-key'); // list rooms svc.listRooms().then((rooms: Room[]) => { console.log('existing rooms', rooms); }); // create a new room const opts = { name: 'myroom', // timeout in seconds emptyTimeout: 10 * 60, maxParticipants: 20, }; sdc.createRoom(opts).then((room: Room) => { console.log('room created', room); }); // delete a room svc.deleteRoom('myroom').then(() => { console.log('room deleted'); }); ``` -------------------------------- ### Configure End-to-End Encryption (E2EE) in Node.js Source: https://context7.com/livekit/node-sdks/llms.txt Sets up end-to-end encryption for media tracks using AES-GCM. Requires a shared secret key and salt. E2EE can be enabled/disabled at runtime and keys can be rotated or ratcheted. ```typescript import { Room, EncryptionType } from '@livekit/rtc-node'; // ---- Connect with E2EE enabled ---- const room = new Room(); const sharedKey = new TextEncoder().encode('my-shared-secret-key-32-bytes!!!'); await room.connect(process.env.LIVEKIT_URL!, process.env.LIVEKIT_TOKEN!, { autoSubscribe: true, encryption: { keyProviderOptions: { sharedKey, ratchetSalt: new TextEncoder().encode('LKFrameEncryptionKey'), ratchetWindowSize: 16, }, encryptionType: EncryptionType.GCM, }, }); // Access the E2EE manager after connecting const e2eeManager = room.e2eeManager!; // Enable/disable E2EE at runtime e2eeManager.setEnabled(true); // Key provider for rotating keys const keyProvider = e2eeManager.keyProvider; // Set a new shared key for all participants (key rotation) const newKey = crypto.getRandomValues(new Uint8Array(32)); keyProvider.setSharedKey(newKey, 1); // keyIndex = 1 // Ratchet the shared key forward (forward secrecy) const ratchetedKey = keyProvider.ratchetSharedKey(1); console.log('New key after ratchet:', ratchetedKey); // Per-participant key management keyProvider.setKey('participant-identity', 0); const exportedKey = keyProvider.exportKey('participant-identity', 0); // Inspect per-participant frame cryptors const cryptors = e2eeManager.frameCryptors(); cryptors.forEach((c) => { console.log(`Cryptor for ${c.participantIdentity}: enabled=${c.enabled}, keyIndex=${c.keyIndex}`); c.setEnabled(true); c.setKeyIndex(1); }); ```