Skip to content

How to#

This page is a collection of the most common operations you may want to perform in your application while integrating OpenVidu. Depending on the scope of the operation, these operations will be performed on the client side using a LiveKit Client SDK, or on the server side using a LiveKit Server SDK (or directly using the HTTP server API). Consider the architecture of an OpenVidu application:

OpenVidu app architecture

You can use this page as a cheat sheet to know at a glance how to do something, and you have links to the LiveKit reference documentation of each operation for a more detailed explanation.

All client side operations are exemplified using the LiveKit JS Client SDK. For other client SDKs, refer to the corresponding LiveKit reference documentation.

Generate access tokens#

The application client needs an access token to connect to a Room. This token must be generated by the application server. Visit LiveKit reference documentation to learn how to generate access tokens:

Reference docs

Manage Rooms#

Connect to a Room#

To connect to a Room you need the URL of your OpenVidu deployment (which is a WebSocket URL) and the access token generated by your application server.

import { Room } from "livekit-client";

const room = new Room();
await room.connect(wsUrl, token);

Reference docs


Disconnect from a Room#

await room.disconnect();

Reference docs


Publish a Track#

You can directly publish the default camera and microphone of the device using methods setCameraEnabled and setMicrophoneEnabled of the LocalParticipant object:

// Publish a video track from the default camera
await room.localParticipant.setCameraEnabled(true);
// Publish an audio track from the default microphone
await room.localParticipant.setMicrophoneEnabled(true);

It is also possible to publish both of them at the same time using method LocalParticipant.enableCameraAndMicrophone, which has the advantage of showing a single permission dialog to the user:

// Publish both default video and audio tracks triggering a single permission dialog
await room.localParticipant.enableCameraAndMicrophone();

To craft a custom Track, you can use the LocalParticipant.createTracks method and publish them with LocalParticipant.publishTrack:

var tracks = await room.localParticipant.createTracks({
  audio: {
    deviceId: "default",
    autoGainControl: true,
    echoCancellation: true,
    noiseSuppression: true
  },
  video: {
    deviceId: 'frontcamera';
    facingMode: 'user'
  },
});
await Promise.all([
    room.localParticipant.publishTrack(tracks[0]),
    room.localParticipant.publishTrack(tracks[1]),
]);

Reference docs


Mute/Unmute a Track#

To mute the default camera and microphone Tracks:

await room.localParticipant.setCameraEnabled(false);
await room.localParticipant.setMicrophoneEnabled(false);

To mute/unmute a custom Track:

// Mute the track
await track.mute();

// Unmute the track
await track.unmute();

Reference docs


Unpublish a Track#

To completely stop sending a Track to the Room, you must unpublish it:

await room.localParticipant.unpublishTrack(track, true);

The second boolean parameter indicates if the local Track should be stopped. This usually means freeing the device capturing it (switching off the camera LED, for example).

Reference docs


Send messages#

You can share information between Participants of a Room in different ways.

First of all, you can set Room metadata that will be available for all clients in the Room object. You do so in your application server when calling the CreateRoom API (available for all LiveKit Server SDKs and the HTTP Server API). The Room metadata will be available in the client side like this:

console.log(room.metadata);

You can update the Room metadata at any time from your application server with the UpdateRoomMetadata API (available for all LiveKit Server SDKs and the HTTP Server API). The client side will be notified of the change with the roomMetadataChanged event of the Room object:

room.on('roomMetadataChanged', (metadata) => {
  console.log('New room metadata', metadata);
});

Secondly, you can also set Participant metadata. You do so when creating an access token in your application server, setting metadata field of the JWT.

Participants can also update their own metadata from the client side, if their access token was created with grant canUpdateOwnMetadata.

room.localParticipant.setMetadata('new metadata');

The client side will be notified of the change with the participantMetadataChanged event of the Room and/or Participant object:

// To handle all metadata changes of all participants
room.on(RoomEvent.ParticipantMetadataChanged, (previousMetadata: string, participant) => {
  console.log('New metadata for participant', participant.identity, participant.metadata);
});

// To handle only metadata changes of a specific participant
participant.on(ParticipantEvent.ParticipantMetadataChanged, (previousMetadata) => {
    console.log('New metadata for participant', participant.identity, participant.metadata);
});

Finally, you can send messages to Participants in the Room using the LocalParticipant.publishData method:

const data: Uint8Array = new TextEncoder().encode(JSON.stringify(''));
room.localParticipant.publishData(data, { reliable: true, topic: 'chat', destinationIdentities: ['participant-identity'] });

The DataPublishOptions allow setting the reliability of the message (depending on the nature of the message it can be sent as a reliable or lossy message), a topic to easily filter messages, and the participants that will receive the message.

The client side will be notified of the message with the dataReceived event of the Room and/or Participant object:

// To receive all messages from the Room
room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant: Participant, kind: DataPacket_Kind) => {
  const strData = new TextDecoder().decode(payload);
  console.log('Received data from', participant.identity, strData);
});

// To receive messages only from a specific participant
participant.on(ParticipantEvent.DataReceived, (payload: Uint8Array, kind: DataPacket_Kind) => {
  const strData = new TextDecoder().decode(payload);
  console.log('Received data from', participant.identity, strData);
});

Reference docs


From your application server#

Except for the generation of access tokens, it is possible for all the logic of your application to be contained entirely on the client side. Nonetheless, some use cases may require the management of the Rooms from the server side.

These operations are only available in the server SDKs, and not in the client SDKs:

  • Closing a Room. From the client side, a user can only leave his own Room.
  • Removing any Participant from a Room. From the client side, a user can only leave his own Room.
  • Muting any Track of any Participant. From the client side, a user can only mute/unmute his own Tracks.
  • Updating the metadata of any Participant. From the client side, a user can only update his own metadata.
  • Updating the metadata of the Room. From the client side this is not possible.
  • Egress operations. Egress cannot be started and stopped on demand by users from the client side.
  • Ingress operations. Ingress cannot be started and stopped on demand by users from the client side.

You have here the complete list of the server-side operations, documented for the HTTP Server API. All the LiveKit Server SDKs have the same operations.

  • RoomService: to manage Rooms and Participants.
  • Egress: to manage egress operations.
  • Ingress: to manage ingress operations.

Screen Sharing#

To quickly publish a screen sharing Track:

await room.localParticipant.setScreenShareEnabled(true);

You can also create custom screen tracks, for example capturing the audio of the screen and fine-tuning the video capture options (checkout the ScreenTrackOptions interface for detailed information):

const screenTracks = await room.localParticipant.createScreenTracks({
    audio: true,
    contentHint: "detail",
    preferCurrentTab: true,
    video: {
        displaySurface: "window"
    }
});
await Promise.all([
    room.localParticipant.publishTrack(screenTracks[0]),
    room.localParticipant.publishTrack(screenTracks[1]),
]);

Reference docs

Virtual Background#

It is possible to apply a virtual background to video tracks. In this way you can blur the background or replace it with an image.

It is necessary to install an additional dependency to use this feature:

npm add @livekit/track-processors

To blur the background:

import { BackgroundBlur } from '@livekit/track-processors';

const videoTrack = await createLocalVideoTrack();
const blur = BackgroundBlur(10);
await videoTrack.setProcessor(blur);

To replace the background with an image:

import { VirtualBackground } from '@livekit/track-processors';

const videoTrack = await createLocalVideoTrack();
const image = VirtualBackground('https://picsum.photos/400');
await videoTrack.setProcessor(image);

GitHub Repository

Recording#

You can record your Rooms using the Egress module. Egress allows exporting media from a Room in different formats, including

  • Room Composite Egress: a single video output with all the Tracks of a Room composited in a layout. You can even create your custom layouts.
  • Track Composite Egress: a single video output combining an audio Track and a video Track.
  • Track Egress: individual outputs for each Track of a Room.

Visit the LiveKit reference documentation for a detailed explanation of Egress:

Reference docs

Webhooks#

Your application server may receive webhooks coming from the OpenVidu deployment. These webhooks inform about events happening in the Rooms, including when a Room is created and finished, when a Participant joins and leaves a Room, when a Track is published and unpublished, and when Egress/Ingress operations take place in a Room.

Every application server tutorial here is ready to receive webhooks: Application Server Tutorials.

Visit the LiveKit reference documentation for a detailed explanation of each webhook event:

Reference docs