API
The Egress API is available within our server SDKs and CLI:
Requests to the Egress API need the roomRecord permission on the access token.
Start every new egress with StartEgress, which takes one source (a layout template, a web page, or tracks from a room) and one or more outputs. The five source-specific egress APIs it replaces are deprecated.
You can also use curl to interact with the Egress APIs. To do so, POST the arguments in JSON format to:
https://<your-livekit-host>/twirp/livekit.Egress/<MethodName>
For example:
% curl -X POST https://<your-livekit-host>/twirp/livekit.Egress/StartEgress \-H 'Authorization: Bearer <livekit-access-token>' \-H 'Content-Type: application/json' \-d '{"room_name": "your-room", "template": {"layout": "grid"}, "outputs": [{"segments": {"filename_prefix": "your-hls-playlist", "playlist_name": "your-hls-playlist.m3u8"}}], "storage": {"s3": {"access_key": "<key>", "secret": "<secret>", "bucket": "<bucket>", "region": "<bucket-region>"}}}'
{"egress_id":"EG_MU4QwhXUhWf9","room_id":"<room-id>","room_name":"your-room","status":"EGRESS_STARTING"...}
All RPC definitions and options can be found here .
StartEgress
Starts an egress. Configure a source and one or more outputs: the source determines what is captured, and the outputs determine where it is sent. It replaces the five source-specific egress APIs below.
StartEgress is available on LiveKit Cloud, and requires LiveKit server v1.13.5 or later when self-hosting. Use the latest version of your server SDK or the LiveKit CLI.
| Parameter | Type | Required | Description |
|---|---|---|---|
room_name | string | With template or media. | Room to capture. Required when using template or media. A web source records an arbitrary URL, so it doesn't need one. |
template | TemplateSource | Composite the room using a layout template. Set exactly one of template, web, or media. | |
web | WebSource | Record any URL in a headless browser. Set exactly one of template, web, or media. | |
media | MediaSource | Capture tracks directly through the SDK. Set exactly one of template, web, or media. | |
preset | EncodingOptionsPreset | Encoding preset. Defaults to H264_720P_30. Set PASSTHROUGH to skip transcoding. Set at most one of preset or advanced. | |
advanced | EncodingOptions | Explicit encoding options. Set at most one of preset or advanced. | |
outputs | array<Output> | yes | Where to write the result. At least one. |
storage | StorageConfig | Default storage for outputs that don't set their own. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
Each deprecated API can be replaced with StartEgress using a specific source type:
| Deprecated API | Source type |
|---|---|
| StartRoomCompositeEgress | TemplateSource |
| StartWebEgress | WebSource |
| StartParticipantEgress | MediaSource with participant_video |
| StartTrackCompositeEgress | MediaSource with video_track_id and audio.routes |
| StartTrackEgress | MediaSource with the PASSTHROUGH preset |
By default a MediaSource decodes and re-encodes what it captures. To export a track without transcoding, as StartTrackEgress did, set preset to PASSTHROUGH. Egress then writes the track in its native container and skips codec negotiation entirely.
Passthrough captures exactly one track to one file, so it has its own constraints:
- The source must be a
MediaSource. Template and web sources are rejected. - Select exactly one track by ID: either
video_track_idor a singleAudioRoutematching ontrack_id. Selecting both or neither is rejected, as areparticipant_video,capture_all, more than one route, and routes matching on identity or kind. - Give exactly one output, and it must be a
FileOutput. Stream, segment, and image outputs are rejected. - Leave
file_typeunset. Egress picks the container from the codec of the track, and an explicit type is rejected.
The StartTrackEgress API also streams raw audio to a websocket_url. To do this with StartEgress, use a StreamOutput with the WEBSOCKET protocol. Note that this transcodes, since passthrough and stream outputs can't be combined.
StartRoomCompositeEgress (deprecated)
StartRoomCompositeEgress is deprecated and will be removed in a future release. Use StartEgress with a TemplateSource instead.
Starts a new Composite Recording using a web browser as the rendering engine.
| Parameter | Type | Required | Description |
|---|---|---|---|
room_name | string | yes | Name of room to record. |
layout | string | Layout parameter that is passed to the template. | |
audio_only | bool | True if resulting output should only contain audio. To get the audio-only billing rate , also leave layout and custom_base_url empty. | |
audio_mixing | AudioMixing | Audio mixing mode to use when audio_only is true. Defaults to DEFAULT_MIXING: All users are mixed together. | |
video_only | bool | True if resulting output should only contain video. | |
custom_base_url | string | URL to the page that would composite tracks, uses embedded templates if left blank. | |
file_outputs | EncodedFileOutput[] | Output to MP4 file. Currently only supports a single entry. | |
segment_outputs | SegmentedFileOutput[] | Output to HLS segments. Currently only supports a single entry. | |
stream_outputs | StreamOutput[] | Output to a stream. Currently only supports a single entry, though it could include multiple destination URLs. | |
image_outputs | ImageOutput[] | Output to a succession of snapshot images taken at a given interval (thumbnails). Currently only supports a single entry. | |
preset | EncodingOptionsPreset | Encoding preset to use. Only one of preset or advanced could be set. | |
advanced | EncodingOptions | Advanced encoding options. Only one of preset or advanced could be set. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
StartParticipantEgress (deprecated)
StartParticipantEgress is deprecated and will be removed in a future release. Use StartEgress with a MediaSource and participant_video instead.
Starts a new Participant Egress.
| Parameter | Type | Required | Description |
|---|---|---|---|
room_name | string | yes | Name of room to record. |
identity | string | yes | Identity of the participant to record. |
screen_share | bool | True to record the participant's screen share instead of their camera. | |
file_outputs | EncodedFileOutput[] | Output to MP4 file. Currently only supports a single entry. | |
stream_outputs | StreamOutput[] | Output to a stream. Currently only supports a single entry, though it could include multiple destination URLs. | |
segment_outputs | SegmentedFileOutput[] | Output to HLS segments. Currently only supports a single entry. | |
image_outputs | ImageOutput[] | Output to a succession of snapshot images taken at a given interval (thumbnails). Currently only supports a single entry. | |
preset | EncodingOptionsPreset | Encoding preset to use. Only one of preset or advanced could be set. | |
advanced | EncodingOptions | Advanced encoding options. Only one of preset or advanced could be set. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
StartTrackCompositeEgress (deprecated)
StartTrackCompositeEgress is deprecated and will be removed in a future release. Use StartEgress with a MediaSource instead, setting video_track_id and routing audio with AudioConfig.
Starts a new Track Composite.
| Parameter | Type | Required | Description |
|---|---|---|---|
room_name | string | yes | Name of room to record. |
audio_track_id | string | ID of audio track to composite. | |
video_track_id | string | ID of video track to composite. | |
file_outputs | EncodedFileOutput[] | Output to MP4 file. Currently only supports a single entry. | |
segment_outputs | SegmentedFileOutput[] | Output to HLS segments. Currently only supports a single entry. | |
stream_outputs | StreamOutput[] | Output to a stream. Currently only supports a single entry, though it could include multiple destination URLs. | |
image_outputs | ImageOutput[] | Output to a succession of snapshot images taken at a given interval (thumbnails). Currently only supports a single entry. | |
preset | EncodingOptionsPreset | Encoding preset to use. Only one of preset or advanced could be set. | |
advanced | EncodingOptions | Advanced encoding options. Only one of preset or advanced could be set. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
StartTrackEgress (deprecated)
StartTrackEgress is deprecated and will be removed in a future release. Use StartEgress with a MediaSource instead, setting preset to PASSTHROUGH to export the track without transcoding.
Starts a new Track Egress.
| Parameter | Type | Required | Description |
|---|---|---|---|
room_name | string | yes | Name of room to record. |
track_id | string | ID of track to record. | |
file | DirectFileOutput | Only one of file or websocket_url can be set. | |
websocket_url | string | URL to websocket to receive audio output. Only one of file or websocket_url can be set. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
StartWebEgress (deprecated)
StartWebEgress is deprecated and will be removed in a future release. Use StartEgress with a WebSource instead.
Starts a new Web Egress.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | yes | URL of the web page to record. |
audio_only | bool | True if resulting output should only contain audio. | |
video_only | bool | True if resulting output should only contain video. | |
file_outputs | EncodedFileOutput[] | Output to MP4 file. Currently only supports a single entry. | |
segment_outputs | SegmentedFileOutput[] | Output to HLS segments. Currently only supports a single entry. | |
stream_outputs | StreamOutput[] | Output to a stream. Currently only supports a single entry, though it could include multiple destination URLs. | |
image_outputs | ImageOutput[] | Output to a succession of snapshot images taken at a given interval (thumbnails). Currently only supports a single entry. | |
preset | EncodingOptionsPreset | Encoding preset to use. Only one of preset or advanced could be set. | |
advanced | EncodingOptions | Advanced encoding options. Only one of preset or advanced could be set. | |
webhooks | WebhookConfig[] | Extra webhooks to send on egress events for this request. |
UpdateLayout
Used to change the web layout on an active RoomCompositeEgress.
| Parameter | Type | Required | Description |
|---|---|---|---|
egress_id | string | yes | Egress ID to update. |
layout | string | yes | Layout to update to. |
lk egress update-layout --id <EGRESS_ID> --layout speaker
import { LiveKitAPI } from 'livekit-server-sdk';const api = new LiveKitAPI();const info = await api.egress.updateLayout(egressId, 'grid-light');
from livekit import apiasync with api.LiveKitAPI() as lkapi:info = await lkapi.egress.update_layout(api.UpdateLayoutRequest(egress_id=egress_id, layout="grid-light"))
require 'livekit'lkapi = LiveKit::LiveKitAPI.newlkapi.egress.update_layout(egress_id, 'grid-light')
import lksdk "github.com/livekit/server-sdk-go/v2"api, err := lksdk.NewLiveKitAPI()info, err := api.Egress().UpdateLayout(ctx, &livekit.UpdateLayoutRequest{EgressId: egressID,Layout: "grid-light",})
import io.livekit.server.LiveKitAPIval api = LiveKitAPI.createClient(host, apiKey, secret)val info = api.egress.updateLayout(egressId, "grid-light").execute().body()
use livekit_api::services::LiveKitApi;let api = LiveKitApi::with_api_key(host, api_key, api_secret);let info = api.egress().update_layout(egress_id, "grid-light").await?;
UpdateStream
Used to add or remove stream URLs from an active stream.
Note: you can only add outputs to an Egress that was started with stream_outputs set.
| Parameter | Type | Required | Description |
|---|---|---|---|
egress_id | string | yes | Egress ID to update. |
add_output_urls | string[] | URLs to add to the egress as output destinations. | |
remove_output_urls | string[] | URLs to remove from the egress. |
lk egress update-stream \--id <EGRESS_ID> \--add-urls "rtmp://a.rtmp.youtube.com/live2/stream-key"
import { LiveKitAPI, StreamOutput, StreamProtocol } from 'livekit-server-sdk';const api = new LiveKitAPI();const streamOutput = new StreamOutput({protocol: StreamProtocol.RTMP,urls: ['rtmp://live.twitch.tv/app/<stream-key>'],});let info = await api.egress.startRoomCompositeEgress('my-room', { stream: streamOutput });const streamEgressId = info.egressId;info = await api.egress.updateStream(streamEgressId, ['rtmp://a.rtmp.youtube.com/live2/stream-key',]);
from livekit import apiasync with api.LiveKitAPI() as lkapi:info = await lkapi.egress.start_room_composite_egress(api.RoomCompositeEgressRequest(room_name="my-room",layout="speaker",stream_outputs=[api.StreamOutput(protocol=api.StreamProtocol.RTMP,urls=["rtmp://live.twitch.tv/app/<stream-key>"],)],))info = await lkapi.egress.update_stream(api.UpdateStreamRequest(egress_id=info.egress_id,add_output_urls=["rtmp://a.rtmp.youtube.com/live2/stream-key"],))
require 'livekit'lkapi = LiveKit::LiveKitAPI.new# to add and remove streamslkapi.egress.update_stream('egress-id',add_output_urls: ['rtmp://new-url'],remove_output_urls: ['rtmp://old-url'])
import lksdk "github.com/livekit/server-sdk-go/v2"api, err := lksdk.NewLiveKitAPI()streamRequest := &livekit.RoomCompositeEgressRequest{RoomName: "my-room",Layout: "speaker",StreamOutputs: []*livekit.StreamOutput{{Protocol: livekit.StreamProtocol_RTMP,Urls: []string{"rtmp://live.twitch.tv/app/<stream-key>"},}},}info, err := api.Egress().StartRoomCompositeEgress(ctx, streamRequest)streamEgressID := info.EgressIdinfo, err = api.Egress().UpdateStream(ctx, &livekit.UpdateStreamRequest{EgressId: streamEgressID,AddOutputUrls: []string{"rtmp://a.rtmp.youtube.com/live2/stream-key"},})
import io.livekit.server.LiveKitAPIval api = LiveKitAPI.createClient(host, apiKey, secret)val info = api.egress.updateStream("egressId",listOf("rtmp://new-url"),listOf("rtmp://old-url"),).execute().body()
use livekit_api::services::LiveKitApi;let api = LiveKitApi::with_api_key(host, api_key, api_secret);let info = api.egress().update_stream("egress-id",vec!["rtmp://new-url".to_string()],vec!["rtmp://old-url".to_string()],).await?;
ListEgress
Used to list active egress. Does not include completed egress.
lk egress list
import { LiveKitAPI } from 'livekit-server-sdk';const api = new LiveKitAPI();const res = await api.egress.listEgress();
from livekit import apiasync with api.LiveKitAPI() as lkapi:res = await lkapi.egress.list_egress(api.ListEgressRequest())
require 'livekit'lkapi = LiveKit::LiveKitAPI.new# to list egress on myroomlkapi.egress.list_egress(room_name: 'myroom')# to list all egresseslkapi.egress.list_egress
import lksdk "github.com/livekit/server-sdk-go/v2"api, err := lksdk.NewLiveKitAPI()res, err := api.Egress().ListEgress(ctx, &livekit.ListEgressRequest{})
import io.livekit.server.LiveKitAPIval api = LiveKitAPI.createClient(host, apiKey, secret)val egressInfos = api.egress.listEgress().execute().body()
use livekit_api::services::{egress::EgressListOptions, LiveKitApi};let api = LiveKitApi::with_api_key(host, api_key, api_secret);let res = api.egress().list_egress(EgressListOptions::default()).await?;
StopEgress
Stops an active egress.
lk egress stop --id <EGRESS_ID>
import { LiveKitAPI } from 'livekit-server-sdk';const api = new LiveKitAPI();const info = await api.egress.stopEgress(egressId);
from livekit import apiasync with api.LiveKitAPI() as lkapi:info = await lkapi.egress.stop_egress(api.StopEgressRequest(egress_id=egress_id))
require 'livekit'lkapi = LiveKit::LiveKitAPI.newlkapi.egress.stop_egress('egress-id')
import lksdk "github.com/livekit/server-sdk-go/v2"api, err := lksdk.NewLiveKitAPI()info, err := api.Egress().StopEgress(ctx, &livekit.StopEgressRequest{EgressId: egressID,})
import io.livekit.server.LiveKitAPIval api = LiveKitAPI.createClient(host, apiKey, secret)val info = api.egress.stopEgress("egressId").execute().body()
use livekit_api::services::LiveKitApi;let api = LiveKitApi::with_api_key(host, api_key, api_secret);let info = api.egress().stop_egress("egress-id").await?;
Types
The Egress service includes the following types.
ListEgressResponse
| Field | Type | Description |
|---|---|---|
| items | array<EgressInfo> | List of egress endpoints. |
EgressInfo
Returned by start, update, list, and stop operations. Describes the egress and its status.
| Field | Type | Description |
|---|---|---|
| egress_id | string | Unique egress ID. |
| room_id | string | Room ID. |
| room_name | string | Room name. |
| source_type | EgressSourceType | Whether the egress was started from web or SDK. |
| status | EgressStatus | Current egress status. |
| started_at | int64 | When the egress started. |
| ended_at | int64 | When the egress ended. |
| updated_at | int64 | Last update timestamp. |
| details | string | Additional status details. |
| error | string | Error message, if any. |
| error_code | int32 | Error code, if any. |
| request | StartEgressRequest | ExportReplayRequest | RoomCompositeEgressRequest | WebEgressRequest | ParticipantEgressRequest | TrackCompositeEgressRequest | TrackEgressRequest | The request that started this egress. StartEgressRequest for egresses started with StartEgress. The five source-specific requests are deprecated. |
| stream_results | array<StreamInfo> | Results per stream output. |
| file_results | array<FileInfo> | Results per file output. |
| segment_results | array<SegmentsInfo> | Results per segmented output. |
| image_results | array<ImagesInfo> | Results per image output. |
| manifest_location | string | Location of the manifest file, if applicable. |
| backup_storage_used | bool | Whether backup storage was used. |
EgressStatus
Enum. Egress lifecycle status:
| Name | Value | Description |
|---|---|---|
| EGRESS_STARTING | 0 | Egress is starting. |
| EGRESS_ACTIVE | 1 | Egress is active and recording or streaming. |
| EGRESS_ENDING | 2 | Egress is shutting down. |
| EGRESS_COMPLETE | 3 | Egress completed successfully. |
| EGRESS_FAILED | 4 | Egress failed. |
| EGRESS_ABORTED | 5 | Egress was aborted. |
| EGRESS_LIMIT_REACHED | 6 | Egress limit was reached. |
EgressSourceType
Enum. Source of the egress:
| Name | Value | Description |
|---|---|---|
| EGRESS_SOURCE_TYPE_WEB | 0 | Started from the web (e.g. Cloud dashboard). |
| EGRESS_SOURCE_TYPE_SDK | 1 | Started from the SDK or API. |
StreamInfo
Per-stream output result.
| Field | Type | Description |
|---|---|---|
| url | string | Stream URL. |
| started_at | int64 | When the stream started. |
| ended_at | int64 | When the stream ended. |
| duration | int64 | Duration in nanoseconds. |
| status | StreamInfo.Status | Stream status. |
| error | string | Error message, if any. |
| last_retry_at | int64 | Last retry timestamp. |
| retries | uint32 | Number of retries. |
StreamInfo.Status
Enum. Stream output status:
| Name | Value | Description |
|---|---|---|
| ACTIVE | 0 | Stream is active. |
| FINISHED | 1 | Stream finished. |
| FAILED | 2 | Stream failed. |
FileInfo
Per-file output result.
| Field | Type | Description |
|---|---|---|
| filename | string | Output filename. |
| started_at | int64 | When the file recording started. |
| ended_at | int64 | When the file recording ended. |
| duration | int64 | Duration in nanoseconds. |
| size | int64 | File size in bytes. |
| location | string | Storage location (e.g. S3 URL). |
SegmentsInfo
Per-segmented-output result (e.g. HLS).
| Field | Type | Description |
|---|---|---|
| playlist_name | string | Playlist filename. |
| live_playlist_name | string | Live playlist path, if configured. |
| duration | int64 | Total duration in nanoseconds. |
| size | int64 | Total size in bytes. |
| playlist_location | string | Playlist storage location. |
| live_playlist_location | string | Live playlist storage location. |
| segment_count | int64 | Number of segments. |
| started_at | int64 | When the recording started. |
| ended_at | int64 | When the recording ended. |
ImagesInfo
Per-image-output result.
| Field | Type | Description |
|---|---|---|
| filename_prefix | string | Prefix used for image filenames. |
| image_count | int64 | Number of images captured. |
| started_at | int64 | When capture started. |
| ended_at | int64 | When capture ended. |
TemplateSource
Composites a room using a layout template rendered in a headless browser. The service generates a token, builds the recorder URL, and waits for the template to signal that it's ready.
| Field | Type | Description |
|---|---|---|
| layout | string | Optional. Layout name passed to the template. |
| audio_only | bool | Optional. Record audio only. |
| video_only | bool | Optional. Record video only. |
| custom_base_url | string | Optional. URL of a custom template. Uses the embedded templates when empty. |
To get the audio-only billing rate , set audio_only and leave both layout and custom_base_url empty. Those three conditions together let the service capture the room directly instead of starting a browser.
WebSource
Records any URL in a headless browser. Unlike TemplateSource, it isn't tied to a room, so it can record content that isn't a LiveKit session.
| Field | Type | Description |
|---|---|---|
| url | string | Required. Page to record. Must be http:// or https://. |
| audio_only | bool | Optional. Record audio only. |
| video_only | bool | Optional. Record video only. |
| await_start_signal | bool | Optional. Wait for the page to signal that it's ready before recording. |
MediaSource
Captures tracks directly from a room through the SDK, with no browser. Unifies the deprecated Participant, TrackComposite, and Track egress requests.
| Field | Type | Description |
|---|---|---|
| video_track_id | string | Optional. Captures exactly this track. Set at most one of video_track_id or participant_video. |
| participant_video | ParticipantVideo | Optional. Captures one participant's camera or screen share. Set at most one of video_track_id or participant_video. |
| audio | AudioConfig | Optional. Which audio to capture, and which channel each track lands in. |
Omit audio to capture video only, or omit the video selector to capture audio only. A request that selects neither fails.
ParticipantVideo
Selects one participant's video track.
| Field | Type | Description |
|---|---|---|
| identity | string | Required. Identity of the participant to capture. |
| prefer_screen_share | bool | Optional. Capture the participant's screen share instead of their camera. When set, only a screen share track is captured. There's no fallback to the camera. |
AudioConfig
Selects which audio to capture and routes it to output channels.
| Field | Type | Description |
|---|---|---|
| capture_all | bool | Optional. Capture every audio track that no route matches, mixed into both channels. |
| routes | array<AudioRoute> | Optional. Per-track and per-participant channel assignments. |
Routes are evaluated in order and the first match wins, so list the most specific matches first. A track matched by a route is captured and mixed into the channel that route specifies. A track no route matches is captured only when capture_all is set, and then lands in both channels.
To record an agent and a caller on separate channels, route the agent to the left channel and standard participants to the right. This replaces the deprecated AudioMixing modes: DEFAULT_MIXING is equivalent to setting capture_all alone, while dual-channel recording becomes explicit routes. StartEgress has no equivalent of DUAL_CHANNEL_ALTERNATE, which assigned channels in subscription order at runtime. Assign channels per participant or per track instead.
AudioRoute
Matches audio and assigns it to a channel.
| Field | Type | Description |
|---|---|---|
| track_id | string | Matches one track by ID. Set exactly one of track_id, participant_identity, or participant_kind. |
| participant_identity | string | Matches every audio track from one participant. Set exactly one of track_id, participant_identity, or participant_kind. |
| participant_kind | ParticipantInfo.Kind | Matches every audio track from participants of this kind, such as AGENT or SIP. Set exactly one of track_id, participant_identity, or participant_kind. |
| channel | AudioChannel | Channel the matched audio is mixed into. Defaults to both. |
AudioChannel
Enum. Output channel for matched audio:
| Name | Value | Description |
|---|---|---|
| AUDIO_CHANNEL_BOTH | 0 | Mix into both channels. |
| AUDIO_CHANNEL_LEFT | 1 | Mix into the left channel only. |
| AUDIO_CHANNEL_RIGHT | 2 | Mix into the right channel only. |
AudioMixing
Enum. Audio mixing mode when recording audio only:
| Name | Value | Description |
|---|---|---|
| DEFAULT_MIXING | 0 | All users are mixed together. |
| DUAL_CHANNEL_AGENT | 1 | Agent audio in the left channel, all other audio in the right channel. |
| DUAL_CHANNEL_ALTERNATE | 2 | Each new audio track alternates between left and right channels. |
Output
One output destination. Every StartEgress request needs at least one.
| Field | Type | Description |
|---|---|---|
| file | FileOutput | Record to a single file. Set exactly one of file, stream, segments, or images. |
| stream | StreamOutput | Stream to RTMP, SRT, or WebSocket. Set exactly one of file, stream, segments, or images. |
| segments | SegmentedFileOutput | Record as HLS segments. Set exactly one of file, stream, segments, or images. |
| images | ImageOutput | Capture thumbnails at an interval. Set exactly one of file, stream, segments, or images. |
| storage | StorageConfig | Optional. Storage for this output. Overrides the request-level storage. |
Behavior
Output handling follows a few rules:
- A request can combine one file output, one stream output, one segment output, and any number of image outputs. Egress transcodes once and writes to all of them. Requesting two of the same kind fails, except for images.
- A WebSocket stream output carries audio only. If the request also selects video, Egress drops the video and streams the audio rather than returning an error.
- An image-only request records video only, and its audio is ignored.
FileOutput
Records to a single file. Replaces the deprecated EncodedFileOutput and DirectFileOutput. Unlike those, it carries no storage fields of its own: set storage with StorageConfig on the output or on the request.
| Field | Type | Description |
|---|---|---|
| file_type | EncodedFileType | Optional. Output format. Chosen from the codecs when unset. |
| filepath | string | Optional. Path and filename within the storage bucket. Supports templating. |
| disable_manifest | bool | Optional. Don't upload the JSON manifest file. Defaults to false. |
EncodedFileType
Enum. Encoded file format:
| Name | Value | Description |
|---|---|---|
| DEFAULT_FILETYPE | 0 | File type chosen based on codecs. |
| MP4 | 1 | MP4 container. |
| OGG | 2 | OGG container. |
| MP3 | 3 | MP3 audio. |
EncodedFileOutput
| Field | Type | Description |
|---|---|---|
| file_type | EncodedFileType | Optional. Output file type. Default chosen from codecs. |
| filepath | string | Output path. See egress docs for templating. Default {room_name}-{time}. |
| disable_manifest | bool | If true, do not upload manifest file. Default false. |
| s3 | S3Upload | S3-compatible storage. Only one storage output. |
| gcp | GCPUpload | Google Cloud Storage. Only one storage output. |
| azure | AzureBlobUpload | Azure Blob Storage. Only one storage output. |
| aliOSS | AliOSSUpload | Alibaba Cloud OSS. Only one storage output. |
DirectFileOutput
| Field | Type | Description |
|---|---|---|
| filepath | string | Output path. See egress docs for templating. Default {track_id}-{time}. |
| disable_manifest | bool | If true, do not upload manifest file. Default false. |
| s3 | S3Upload | S3-compatible storage. Only one storage output. |
| gcp | GCPUpload | Google Cloud Storage. Only one storage output. |
| azure | AzureBlobUpload | Azure Blob Storage. Only one storage output. |
| aliOSS | AliOSSUpload | Alibaba Cloud OSS. Only one storage output. |
SegmentedFileProtocol
Enum. Segmented output protocol:
| Name | Value | Description |
|---|---|---|
| DEFAULT_SEGMENTED_FILE_PROTOCOL | 0 | Protocol chosen by server. |
| HLS_PROTOCOL | 1 | HLS. |
SegmentedFileSuffix
Enum. Suffix for segment filenames:
| Name | Value | Description |
|---|---|---|
| INDEX | 0 | Numeric index (1, 2, 3, ...). |
| TIMESTAMP | 1 | UTC timestamp. |
SegmentedFileOutput
| Field | Type | Description |
|---|---|---|
| protocol | SegmentedFileProtocol | Optional. Segmented protocol. Default chosen by server. |
| filename_prefix | string | Optional. Prefix for each segment (include paths here). |
| playlist_name | string | Optional. Name of the m3u8 playlist. When empty, matches filename_prefix. |
| live_playlist_name | string | Optional. Path for a live playlist. Omitted if not set. |
| segment_duration | uint32 | Segment length in seconds. Optional. |
| filename_suffix | SegmentedFileSuffix | Optional. INDEX or TIMESTAMP. Default INDEX. |
| disable_manifest | bool | If true, do not upload manifest file. Default false. |
| s3 | S3Upload | S3-compatible storage. Only one storage output. |
| gcp | GCPUpload | Google Cloud Storage. Only one storage output. |
| azure | AzureBlobUpload | Azure Blob Storage. Only one storage output. |
| aliOSS | AliOSSUpload | Alibaba Cloud OSS. Only one storage output. |
StreamProtocol
Enum. Stream output protocol:
| Name | Value | Description |
|---|---|---|
| DEFAULT_PROTOCOL | 0 | Protocol chosen from URLs. |
| RTMP | 1 | RTMP. |
| SRT | 2 | SRT. |
| WEBSOCKET | 3 | Raw audio over a WebSocket. Audio only. |
StreamOutput
| Field | Type | Description |
|---|---|---|
| protocol | StreamProtocol | Required. Stream protocol (e.g. RTMP). |
| urls | array<string> | Required. Destination URLs. |
ImageFileSuffix
Enum. Suffix for image filenames:
| Name | Value | Description |
|---|---|---|
| IMAGE_SUFFIX_INDEX | 0 | Numeric index (1, 2, 3, ...). |
| IMAGE_SUFFIX_TIMESTAMP | 1 | Timestamp. |
| IMAGE_SUFFIX_NONE_OVERWRITE | 2 | No suffix; overwrite the same file with the latest image. |
ImageOutput
| Field | Type | Description |
|---|---|---|
| capture_interval | uint32 | Required. Seconds between each snapshot. |
| width | int32 | Optional. Image width. Defaults to track width. |
| height | int32 | Optional. Image height. Defaults to track height. |
| filename_prefix | string | Optional. Prefix for each image filename (include paths here). |
| filename_suffix | ImageFileSuffix | Optional. INDEX, TIMESTAMP, or NONE_OVERWRITE. Default INDEX. |
| image_codec | ImageCodec | Optional. Image codec (e.g. JPEG). |
| disable_manifest | bool | If true, do not upload manifest file. Default false. |
| s3 | S3Upload | S3-compatible storage. Only one storage output. |
| gcp | GCPUpload | Google Cloud Storage. Only one storage output. |
| azure | AzureBlobUpload | Azure Blob Storage. Only one storage output. |
| aliOSS | AliOSSUpload | Alibaba Cloud OSS. Only one storage output. |
StorageConfig
Specifies where Egress stores output files. Set it on a StartEgress request to apply the same storage configuration to every output, or on an individual Output to override the request-level configuration.
| Field | Type | Description |
|---|---|---|
| s3 | S3Upload | S3-compatible storage. Set at most one of s3, gcp, azure, or aliOSS. |
| gcp | GCPUpload | Google Cloud Storage. Set at most one of s3, gcp, azure, or aliOSS. |
| azure | AzureBlobUpload | Azure Blob Storage. Set at most one of s3, gcp, azure, or aliOSS. |
| aliOSS | AliOSSUpload | Alibaba Cloud OSS. Set at most one of s3, gcp, azure, or aliOSS. |
Egress resolves storage in three steps and uses the first one set: the storage set on the output, then the storage set on the request, then the storage configured on the server. On LiveKit Cloud, local storage isn't available, so a request that resolves to no storage fails.
The deprecated source-specific requests, along with SegmentedFileOutput and ImageOutput, still take s3, gcp, azure, and aliOSS fields directly. Those fields are deprecated. Use StorageConfig instead.
S3Upload
| Field | Type | Description |
|---|---|---|
| access_key | string | S3 access key. |
| secret | string | S3 secret key. |
| session_token | string | Optional. Session token for temporary credentials. |
| assume_role_arn | string | Optional. ARN of role to assume for upload (LiveKit Cloud feature when enabled). |
| assume_role_external_id | string | Optional. External ID for assume role. |
| region | string | Bucket region. Optional. |
| endpoint | string | Custom S3 endpoint URL. Optional. |
| bucket | string | Destination bucket. |
| force_path_style | bool | If true, keep bucket in path (no subdomain). Optional. |
| metadata | map<string, string> | Metadata key-value pairs. Optional. |
| tagging | string | S3 object tagging. Optional. |
| content_disposition | string | Content-Disposition header. Optional. |
| proxy | ProxyConfig | Proxy for uploads. Optional. |
GCPUpload
| Field | Type | Description |
|---|---|---|
| credentials | string | Service account credentials JSON (credentials.json). |
| bucket | string | Destination bucket. |
| proxy | ProxyConfig | Proxy for uploads. Optional. |
AzureBlobUpload
| Field | Type | Description |
|---|---|---|
| account_name | string | Azure storage account name. |
| account_key | string | Azure storage account key. |
| container_name | string | Destination container. |
AliOSSUpload
| Field | Type | Description |
|---|---|---|
| access_key | string | Alibaba Cloud access key. |
| secret | string | Alibaba Cloud secret key. |
| region | string | Bucket region. |
| endpoint | string | Custom endpoint URL. Optional. |
| bucket | string | Destination bucket. |
EncodingOptions
| Field | Type | Description |
|---|---|---|
| width | int32 | Output width. Default 1920. |
| height | int32 | Output height. Default 1080. |
| depth | int32 | Color depth. Default 24. |
| framerate | int32 | Frame rate. Default 30. |
| audio_codec | AudioCodec | Audio codec. Default OPUS. |
| audio_bitrate | int32 | Audio bitrate in kbps. Default 128. |
| audio_quality | int32 | Audio encoder quality setting. Optional. |
| audio_frequency | int32 | Sample rate in Hz. Default 44100. |
| video_codec | VideoCodec | Video codec. Default H264_MAIN. |
| video_bitrate | int32 | Video bitrate in kbps. Default 4500. |
| video_quality | int32 | Video encoder quality setting. Optional. |
| key_frame_interval | double | Key frame interval in seconds. Default 4 for streaming; segment duration for segmented output; encoder default for files. |
EncodingOptionsPreset
Enum. Encoding presets (H.264_MAIN / OPUS unless noted):
| Name | Value | Description |
|---|---|---|
| H264_720P_30 | 0 | 1280×720, 30 fps, 3000 kbps. |
| H264_720P_60 | 1 | 1280×720, 60 fps, 4500 kbps. |
| H264_1080P_30 | 2 | 1920×1080, 30 fps, 4500 kbps. |
| H264_1080P_60 | 3 | 1920×1080, 60 fps, 6000 kbps. |
| PORTRAIT_H264_720P_30 | 4 | 720×1280, 30 fps, 3000 kbps. |
| PORTRAIT_H264_720P_60 | 5 | 720×1280, 60 fps, 4500 kbps. |
| PORTRAIT_H264_1080P_30 | 6 | 1080×1920, 30 fps, 4500 kbps. |
| PORTRAIT_H264_1080P_60 | 7 | 1080×1920, 60 fps, 6000 kbps. |
| PASSTHROUGH | 8 | Skip transcoding and write the track in its native container. Valid only with a MediaSource selecting a single track, and a single FileOutput. See StartEgress for the full constraints. |
ProxyConfig
Proxy server for uploads (S3 and GCP). Use to work around network restrictions to destination buckets.
| Field | Type | Description |
|---|---|---|
| url | string | Proxy URL. |
| username | string | Username for basic auth. Optional. |
| password | string | Password for basic auth. Optional. |
WebhookConfig
Extra webhooks for a specific egress request. Called for egress lifecycle events in addition to project webhooks. See Webhooks.
| Field | Type | Description |
|---|---|---|
| url | string | Webhook URL. |
| signing_key | string | API key to sign the request. Must be defined for the project. |