Guides / Recording & Livestreaming / Egress


Record or livestream your LiveKit rooms


LiveKit Egress gives you a powerful and consistent set of APIs to export any room or individual tracks from a LiveKit session.

It supports recording to a MP4 file or HLS segements, as well as exporting to livestreaming endpoints like Facebook, Twitch, and YouTube Live via RTMP(s).

When self-hosting LiveKit, Egress is a separate component that needs to be deployed.

Egress Types

Room Composite Egress

Export an entire room's video and/or audio using a web layout rendered by chrome.

Example use case: recording a meeting for team members to watch later.

Track Composite Egress

Sync and export up to one audio and one video track. Will transcode and mux.

Example use case: exporting audio+video from many cameras at once during a production, for use in additional post-production.

Track Egress

Export individual tracks directly. Video tracks are not transcoded.

Example use case: streaming an audio track to a captioning service via websocket.

Supported Output

Egress TypeMP4 FileOGG FileWebM FileHLS (TS SEGMENTS)RTMP(s) StreamWebSocket Stream
Room Composite
Track Composite

Files can be uploaded to any S3 compatible storage, Azure, or GCP.


message S3Upload {
string access_key = 1;
string secret = 2;
string region = 3;
string endpoint = 4;
string bucket = 5;

Egress supports any S3-compatible storage provider, including DigitalOcean Spaces. When endpoint is left empty, it'll use AWS's regional endpoints. region is required when endpoint is not set.

const output = {
fileType: EncodedFileType.MP4,
filepath: 'livekit-demo/room-composite-test.mp4',
s3: {
accessKey: 'aws-access-key',
secret: 'aws-access-secret',
bucket: 'my-bucket',
endpoint: 'https://my.s3.endpoint',
await egressClient.startRoomCompositeEgress('my-room', output);

Google Cloud Storage

message GCPUpload {
bytes credentials = 1;
string bucket = 2;

For Egress to upload to Google Cloud Storage, you'll need to provide credentials in JSON.

This can be obtained by first creating a service account that has permissions to create storage objects (i.e. Storage Object Creator). Then create a key for that account and export as a JSON file. We'll refer to this file as credentials.json.

import * as fs from 'fs';
const content = fs.readFileSync('/path/to/credentials.json')
const output = {
fileType: EncodedFileType.MP4,
filepath: 'livekit-demo/room-composite-test.mp4',
gcp: {
// credentials needs to be a UInt8Array
credentials: content,
bucket: 'my-bucket',
await egressClient.startRoomCompositeEgress('my-room', output);


message AzureBlobUpload {
string account_name = 1;
string account_key = 2;
string container_name = 3;

In order to upload to Azure Blob Storage, you'll need the account's shared access key.

const output = {
fileType: EncodedFileType.MP4,
filepath: 'livekit-demo/room-composite-test.mp4',
azure: {
accountName: 'my-account',
accountKey: 'shared-access-key',
containerName: 'my-container',
await egressClient.startRoomCompositeEgress('my-room', output);

Service Architecture

Depending on your request type, the egress service will either launch a web template in Chrome and connect to the room (room composite requests), or it will use the sdk directly (track and track composite requests). It uses GStreamer to encode, and can output to a file or to one or more streams.

Egress instance


All RPC definitions and options can be found here.

Egress service requires roomRecord permissions in Access Tokens

The Egress API exists within our server SDKs and CLI

The API is part of LiveKit Server, which uses redis to communicate with the Egress service.


See Composite Recording


See Track Composite


See Track Egress


Used to change the web layout on an active RoomCompositeEgress.

const info = await egressClient.updateLayout(egressID, 'grid-light');


Used to add or remove stream urls from an active stream

Note: you can only add or remove outputs from a stream (RTMP output instead of filepath).

const output = {
protocol: StreamProtocol.RTMP,
urls: ['rtmp://<stream-key>']
var info = await egressClient.startRoomCompositeEgress('my-room', 'speaker-dark', output);
const streamEgressID = info.egressId;
info = await egressClient.updateStream(


Used to list active egress. Does not include completed egress.

const res = await egressClient.listEgress();


Stops an active egress.

const info = await egressClient.stopEgress(egressID);


See the deployment docs for more info on deployment, config, and autoscaling.