1syntax = "proto3";
2
3package livekit;
4option go_package = "github.com/livekit/protocol/livekit";
5option csharp_namespace = "LiveKit.Proto";
6option ruby_package = "LiveKit::Proto";
7
8service Egress {
9 // start recording or streaming a room, participant, or tracks
10 rpc StartRoomCompositeEgress(RoomCompositeEgressRequest) returns (EgressInfo);
11 rpc StartTrackCompositeEgress(TrackCompositeEgressRequest) returns (EgressInfo);
12 rpc StartTrackEgress(TrackEgressRequest) returns (EgressInfo);
13
14 // update web composite layout
15 rpc UpdateLayout(UpdateLayoutRequest) returns (EgressInfo);
16
17 // add or remove stream endpoints
18 rpc UpdateStream(UpdateStreamRequest) returns (EgressInfo);
19
20 // list available egress
21 rpc ListEgress(ListEgressRequest) returns (ListEgressResponse);
22
23 // stop a recording or stream
24 rpc StopEgress(StopEgressRequest) returns (EgressInfo);
25}
26
27// composite using a web browser
28message RoomCompositeEgressRequest {
29 string room_name = 1; // required
30 string layout = 2; // (optional)
31 bool audio_only = 3; // (default false)
32 bool video_only = 4; // (default false)
33 string custom_base_url = 5; // (default https://recorder.livekit.io)
34 oneof output { // required
35 EncodedFileOutput file = 6;
36 StreamOutput stream = 7;
37 SegmentedFileOutput segments = 10;
38 }
39 oneof options {
40 EncodingOptionsPreset preset = 8; // (default H264_720P_30)
41 EncodingOptions advanced = 9; // (optional)
42 }
43}
44
45// containerize up to one audio and one video track
46message TrackCompositeEgressRequest {
47 string room_name = 1; // required
48 string audio_track_id = 2; // (optional)
49 string video_track_id = 3; // (optional)
50 oneof output { // required
51 EncodedFileOutput file = 4;
52 StreamOutput stream = 5;
53 SegmentedFileOutput segments = 8;
54 }
55 oneof options {
56 EncodingOptionsPreset preset = 6; // (default H264_720P_30)
57 EncodingOptions advanced = 7; // (optional)
58 }
59}
60
61// record tracks individually, without transcoding
62message TrackEgressRequest {
63 string room_name = 1; // required
64 string track_id = 2; // required
65 oneof output { // required
66 DirectFileOutput file = 3;
67 string websocket_url = 4;
68 }
69}
70
71enum EncodedFileType {
72 DEFAULT_FILETYPE = 0; // file type chosen based on codecs
73 MP4 = 1;
74 OGG = 2;
75}
76
77message EncodedFileOutput {
78 EncodedFileType file_type = 1; // (optional)
79 string filepath = 2; // (optional)
80 oneof output { // required
81 S3Upload s3 = 3;
82 GCPUpload gcp = 4;
83 AzureBlobUpload azure = 5;
84 }
85}
86
87// Used to generate HLS segments or other kind of segmented output
88message SegmentedFileOutput {
89 SegmentedFileProtocol protocol = 1; // (optional)
90 string filename_prefix = 2; // (optional)
91 string playlist_name = 3; // (optional)
92 uint32 segment_duration = 4; // (optional)
93 oneof output { // required
94 S3Upload s3 = 5;
95 GCPUpload gcp = 6;
96 AzureBlobUpload azure = 7;
97 }
98}
99
100message DirectFileOutput {
101 string filepath = 1; // (optional)
102 oneof output { // required
103 S3Upload s3 = 2;
104 GCPUpload gcp = 3;
105 AzureBlobUpload azure = 4;
106 }
107}
108
109message S3Upload {
110 string access_key = 1;
111 string secret = 2;
112 string region = 3;
113 string endpoint = 4;
114 string bucket = 5;
115}
116
117message GCPUpload {
118 bytes credentials = 1;
119 string bucket = 2;
120}
121
122message AzureBlobUpload {
123 string account_name = 1;
124 string account_key = 2;
125 string container_name = 3;
126}
127
128enum StreamProtocol {
129 DEFAULT_PROTOCOL = 0; // protocol chosen based on urls
130 RTMP = 1;
131}
132
133enum SegmentedFileProtocol {
134 DEFAULT_SEGMENTED_FILE_PROTOCOL = 0;
135 HLS_PROTOCOL = 1;
136}
137
138message StreamOutput {
139 StreamProtocol protocol = 1; // required
140 repeated string urls = 2; // required
141}
142
143enum AudioCodec {
144 DEFAULT_AC = 0;
145 OPUS = 1;
146 AAC = 2;
147}
148
149enum VideoCodec {
150 DEFAULT_VC = 0;
151 H264_BASELINE = 1;
152 H264_MAIN = 2;
153 H264_HIGH = 3;
154}
155
156message EncodingOptions {
157 int32 width = 1; // (default 1920)
158 int32 height = 2; // (default 1080)
159 int32 depth = 3; // (default 24)
160 int32 framerate = 4; // (default 30)
161 AudioCodec audio_codec = 5; // (default OPUS)
162 int32 audio_bitrate = 6; // (default 128)
163 int32 audio_frequency = 7; // (default 44100)
164 VideoCodec video_codec = 8; // (default H264_MAIN)
165 int32 video_bitrate = 9; // (default 4500)
166}
167
168enum EncodingOptionsPreset {
169 H264_720P_30 = 0; // 1280x720, 30fps, 3000kpbs, H.264_MAIN / OPUS
170 H264_720P_60 = 1; // 1280x720, 60fps, 4500kbps, H.264_MAIN / OPUS
171 H264_1080P_30 = 2; // 1920x1080, 30fps, 4500kbps, H.264_MAIN / OPUS
172 H264_1080P_60 = 3; // 1920x1080, 60fps, 6000kbps, H.264_MAIN / OPUS
173 PORTRAIT_H264_720P_30 = 4; // 720x1280, 30fps, 3000kpbs, H.264_MAIN / OPUS
174 PORTRAIT_H264_720P_60 = 5; // 720x1280, 60fps, 4500kbps, H.264_MAIN / OPUS
175 PORTRAIT_H264_1080P_30 = 6; // 1080x1920, 30fps, 4500kbps, H.264_MAIN / OPUS
176 PORTRAIT_H264_1080P_60 = 7; // 1080x1920, 60fps, 6000kbps, H.264_MAIN / OPUS
177}
178
179message UpdateLayoutRequest {
180 string egress_id = 1;
181 string layout = 2;
182}
183
184message UpdateStreamRequest {
185 string egress_id = 1;
186 repeated string add_output_urls = 2;
187 repeated string remove_output_urls = 3;
188}
189
190message ListEgressRequest {
191 string room_name = 1; // (optional, used to filter results)
192}
193
194message ListEgressResponse {
195 repeated EgressInfo items = 1;
196}
197
198message StopEgressRequest {
199 string egress_id = 1;
200}
201
202enum EgressStatus {
203 EGRESS_STARTING = 0;
204 EGRESS_ACTIVE = 1;
205 EGRESS_ENDING = 2;
206 EGRESS_COMPLETE = 3;
207 EGRESS_FAILED = 4;
208 EGRESS_ABORTED = 5;
209 EGRESS_LIMIT_REACHED = 6;
210}
211
212message EgressInfo {
213 string egress_id = 1;
214 string room_id = 2;
215 string room_name = 13;
216 EgressStatus status = 3;
217 int64 started_at = 10;
218 int64 ended_at = 11;
219 string error = 9;
220 oneof request {
221 RoomCompositeEgressRequest room_composite = 4;
222 TrackCompositeEgressRequest track_composite = 5;
223 TrackEgressRequest track = 6;
224 }
225 oneof result {
226 StreamInfoList stream = 7;
227 FileInfo file = 8;
228 SegmentsInfo segments = 12;
229 }
230}
231
232message StreamInfoList {
233 repeated StreamInfo info = 1;
234}
235
236message StreamInfo {
237 enum Status {
238 ACTIVE = 0;
239 FINISHED = 1;
240 FAILED = 2;
241 }
242
243 string url = 1;
244 int64 started_at = 2;
245 int64 ended_at = 3;
246 int64 duration = 4;
247 Status status = 5;
248}
249
250message FileInfo {
251 string filename = 1;
252 int64 duration = 6;
253 int64 size = 4;
254 string location = 5;
255}
256
257message SegmentsInfo {
258 string playlist_name = 1;
259 int64 duration = 2;
260 int64 size = 3;
261 string playlist_location = 4;
262 int64 segment_count = 5;
263}