Vendor LiveKit protocol (#11672)

This PR vendors the protobuf files from the LiveKit protocol so that we
don't need to have that entire LiveKit protocol repo as a submodule.

---

Eventually I would like to replace this with the
[`livekit-protocol`](https://crates.io/crates/livekit-protocol) crate,
but there is some churn that needs to happen for that.

The main problem is that we're currently on a different version of
`prost` used by `livekit-protocol`, and upgrading our version of `prost`
means that we now need to source `protoc` ourselves (since it is no
longer available to be compiled from source as part of `prost-build`).

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-05-10 14:18:40 -04:00 committed by GitHub
parent 80d3eafa30
commit c9738a233e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1571 additions and 5 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "crates/live_kit_server/protocol"]
path = crates/live_kit_server/protocol
url = https://github.com/livekit/protocol

View File

@ -1,6 +1,9 @@
fn main() {
prost_build::Config::new()
.type_attribute("SendDataResponse", "#[allow(clippy::empty_docs)]")
.compile_protos(&["protocol/livekit_room.proto"], &["protocol"])
.compile_protos(
&["vendored/protocol/livekit_room.proto"],
&["vendored/protocol"],
)
.unwrap();
}

@ -1 +0,0 @@
Subproject commit 8645a138fb2ea72c4dab13e739b1f3c9ea29ac84

View File

@ -0,0 +1,5 @@
# LiveKit Protocol
This is a vendored copy of the [LiveKit protocol](https://github.com/livekit/protocol).
Vendored at [`8645a138fb2ea72c4dab13e739b1f3c9ea29ac84`](https://github.com/livekit/protocol/tree/8645a138fb2ea72c4dab13e739b1f3c9ea29ac84).

View File

@ -0,0 +1,118 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "livekit_models.proto";
import "livekit_egress.proto";
import "livekit_ingress.proto";
service AnalyticsRecorderService {
rpc IngestStats(stream AnalyticsStats) returns (google.protobuf.Empty){};
rpc IngestEvents(stream AnalyticsEvents) returns (google.protobuf.Empty){};
}
enum StreamType {
UPSTREAM = 0;
DOWNSTREAM = 1;
}
message AnalyticsVideoLayer {
int32 layer = 1;
uint32 packets = 2;
uint64 bytes = 3;
uint32 frames = 4;
}
message AnalyticsStream {
uint32 ssrc = 1;
uint32 primary_packets = 2;
uint64 primary_bytes = 3;
uint32 retransmit_packets = 4;
uint64 retransmit_bytes = 5;
uint32 padding_packets = 6;
uint64 padding_bytes = 7;
uint32 packets_lost = 8;
uint32 frames = 9;
uint32 rtt = 10;
uint32 jitter = 11;
uint32 nacks = 12;
uint32 plis = 13;
uint32 firs = 14;
repeated AnalyticsVideoLayer video_layers = 15;
}
message AnalyticsStat {
string analytics_key = 1;
StreamType kind = 2;
google.protobuf.Timestamp time_stamp = 3;
string node = 4;
string room_id = 5;
string room_name = 6;
string participant_id = 7;
string track_id = 8;
float score = 9;
repeated AnalyticsStream streams = 10;
string mime = 11;
}
message AnalyticsStats {
repeated AnalyticsStat stats = 1;
}
enum AnalyticsEventType {
ROOM_CREATED = 0;
ROOM_ENDED = 1;
PARTICIPANT_JOINED = 2;
PARTICIPANT_LEFT = 3;
TRACK_PUBLISHED = 4;
TRACK_UNPUBLISHED = 5;
TRACK_SUBSCRIBED = 6;
TRACK_UNSUBSCRIBED = 7;
TRACK_PUBLISHED_UPDATE = 10;
PARTICIPANT_ACTIVE = 11;
EGRESS_STARTED = 12;
EGRESS_ENDED = 13;
TRACK_MAX_SUBSCRIBED_VIDEO_QUALITY = 14;
RECONNECTED = 15;
INGRESS_STARTED = 16;
INGRESS_ENDED = 17;
}
message AnalyticsClientMeta {
string region = 1;
string node = 2;
string client_addr = 3;
uint32 client_connect_time = 4;
// udp, tcp, turn
string connection_type = 5;
}
message AnalyticsEvent {
AnalyticsEventType type = 1;
google.protobuf.Timestamp timestamp = 2;
string room_id = 3;
Room room = 4;
string participant_id = 5;
ParticipantInfo participant = 6;
string track_id = 7;
TrackInfo track = 8;
string analytics_key = 10;
ClientInfo client_info = 11;
AnalyticsClientMeta client_meta = 12;
string egress_id = 13;
VideoQuality max_subscribed_video_quality = 14;
ParticipantInfo publisher = 15;
string mime = 16;
EgressInfo egress = 17;
IngressInfo ingress = 18;
}
message AnalyticsEvents {
repeated AnalyticsEvent events = 1;
}

View File

@ -0,0 +1,263 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
service Egress {
// start recording or streaming a room, participant, or tracks
rpc StartRoomCompositeEgress(RoomCompositeEgressRequest) returns (EgressInfo);
rpc StartTrackCompositeEgress(TrackCompositeEgressRequest) returns (EgressInfo);
rpc StartTrackEgress(TrackEgressRequest) returns (EgressInfo);
// update web composite layout
rpc UpdateLayout(UpdateLayoutRequest) returns (EgressInfo);
// add or remove stream endpoints
rpc UpdateStream(UpdateStreamRequest) returns (EgressInfo);
// list available egress
rpc ListEgress(ListEgressRequest) returns (ListEgressResponse);
// stop a recording or stream
rpc StopEgress(StopEgressRequest) returns (EgressInfo);
}
// composite using a web browser
message RoomCompositeEgressRequest {
string room_name = 1; // required
string layout = 2; // (optional)
bool audio_only = 3; // (default false)
bool video_only = 4; // (default false)
string custom_base_url = 5; // (default https://recorder.livekit.io)
oneof output { // required
EncodedFileOutput file = 6;
StreamOutput stream = 7;
SegmentedFileOutput segments = 10;
}
oneof options {
EncodingOptionsPreset preset = 8; // (default H264_720P_30)
EncodingOptions advanced = 9; // (optional)
}
}
// containerize up to one audio and one video track
message TrackCompositeEgressRequest {
string room_name = 1; // required
string audio_track_id = 2; // (optional)
string video_track_id = 3; // (optional)
oneof output { // required
EncodedFileOutput file = 4;
StreamOutput stream = 5;
SegmentedFileOutput segments = 8;
}
oneof options {
EncodingOptionsPreset preset = 6; // (default H264_720P_30)
EncodingOptions advanced = 7; // (optional)
}
}
// record tracks individually, without transcoding
message TrackEgressRequest {
string room_name = 1; // required
string track_id = 2; // required
oneof output { // required
DirectFileOutput file = 3;
string websocket_url = 4;
}
}
enum EncodedFileType {
DEFAULT_FILETYPE = 0; // file type chosen based on codecs
MP4 = 1;
OGG = 2;
}
message EncodedFileOutput {
EncodedFileType file_type = 1; // (optional)
string filepath = 2; // (optional)
oneof output { // required
S3Upload s3 = 3;
GCPUpload gcp = 4;
AzureBlobUpload azure = 5;
}
}
// Used to generate HLS segments or other kind of segmented output
message SegmentedFileOutput {
SegmentedFileProtocol protocol = 1; // (optional)
string filename_prefix = 2; // (optional)
string playlist_name = 3; // (optional)
uint32 segment_duration = 4; // (optional)
oneof output { // required
S3Upload s3 = 5;
GCPUpload gcp = 6;
AzureBlobUpload azure = 7;
}
}
message DirectFileOutput {
string filepath = 1; // (optional)
oneof output { // required
S3Upload s3 = 2;
GCPUpload gcp = 3;
AzureBlobUpload azure = 4;
}
}
message S3Upload {
string access_key = 1;
string secret = 2;
string region = 3;
string endpoint = 4;
string bucket = 5;
}
message GCPUpload {
bytes credentials = 1;
string bucket = 2;
}
message AzureBlobUpload {
string account_name = 1;
string account_key = 2;
string container_name = 3;
}
enum StreamProtocol {
DEFAULT_PROTOCOL = 0; // protocol chosen based on urls
RTMP = 1;
}
enum SegmentedFileProtocol {
DEFAULT_SEGMENTED_FILE_PROTOCOL = 0;
HLS_PROTOCOL = 1;
}
message StreamOutput {
StreamProtocol protocol = 1; // required
repeated string urls = 2; // required
}
enum AudioCodec {
DEFAULT_AC = 0;
OPUS = 1;
AAC = 2;
}
enum VideoCodec {
DEFAULT_VC = 0;
H264_BASELINE = 1;
H264_MAIN = 2;
H264_HIGH = 3;
}
message EncodingOptions {
int32 width = 1; // (default 1920)
int32 height = 2; // (default 1080)
int32 depth = 3; // (default 24)
int32 framerate = 4; // (default 30)
AudioCodec audio_codec = 5; // (default OPUS)
int32 audio_bitrate = 6; // (default 128)
int32 audio_frequency = 7; // (default 44100)
VideoCodec video_codec = 8; // (default H264_MAIN)
int32 video_bitrate = 9; // (default 4500)
}
enum EncodingOptionsPreset {
H264_720P_30 = 0; // 1280x720, 30fps, 3000kpbs, H.264_MAIN / OPUS
H264_720P_60 = 1; // 1280x720, 60fps, 4500kbps, H.264_MAIN / OPUS
H264_1080P_30 = 2; // 1920x1080, 30fps, 4500kbps, H.264_MAIN / OPUS
H264_1080P_60 = 3; // 1920x1080, 60fps, 6000kbps, H.264_MAIN / OPUS
PORTRAIT_H264_720P_30 = 4; // 720x1280, 30fps, 3000kpbs, H.264_MAIN / OPUS
PORTRAIT_H264_720P_60 = 5; // 720x1280, 60fps, 4500kbps, H.264_MAIN / OPUS
PORTRAIT_H264_1080P_30 = 6; // 1080x1920, 30fps, 4500kbps, H.264_MAIN / OPUS
PORTRAIT_H264_1080P_60 = 7; // 1080x1920, 60fps, 6000kbps, H.264_MAIN / OPUS
}
message UpdateLayoutRequest {
string egress_id = 1;
string layout = 2;
}
message UpdateStreamRequest {
string egress_id = 1;
repeated string add_output_urls = 2;
repeated string remove_output_urls = 3;
}
message ListEgressRequest {
string room_name = 1; // (optional, used to filter results)
}
message ListEgressResponse {
repeated EgressInfo items = 1;
}
message StopEgressRequest {
string egress_id = 1;
}
enum EgressStatus {
EGRESS_STARTING = 0;
EGRESS_ACTIVE = 1;
EGRESS_ENDING = 2;
EGRESS_COMPLETE = 3;
EGRESS_FAILED = 4;
EGRESS_ABORTED = 5;
EGRESS_LIMIT_REACHED = 6;
}
message EgressInfo {
string egress_id = 1;
string room_id = 2;
string room_name = 13;
EgressStatus status = 3;
int64 started_at = 10;
int64 ended_at = 11;
string error = 9;
oneof request {
RoomCompositeEgressRequest room_composite = 4;
TrackCompositeEgressRequest track_composite = 5;
TrackEgressRequest track = 6;
}
oneof result {
StreamInfoList stream = 7;
FileInfo file = 8;
SegmentsInfo segments = 12;
}
}
message StreamInfoList {
repeated StreamInfo info = 1;
}
message StreamInfo {
enum Status {
ACTIVE = 0;
FINISHED = 1;
FAILED = 2;
}
string url = 1;
int64 started_at = 2;
int64 ended_at = 3;
int64 duration = 4;
Status status = 5;
}
message FileInfo {
string filename = 1;
int64 duration = 6;
int64 size = 4;
string location = 5;
}
message SegmentsInfo {
string playlist_name = 1;
int64 duration = 2;
int64 size = 3;
string playlist_location = 4;
int64 segment_count = 5;
}

View File

@ -0,0 +1,134 @@
syntax = "proto3";
package livekit;
import "livekit_models.proto";
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
service Ingress {
// Create a new Ingress
rpc CreateIngress(CreateIngressRequest) returns (IngressInfo);
// Update an existing Ingress. Ingress can only be updated when it's in ENDPOINT_WAITING state.
rpc UpdateIngress(UpdateIngressRequest) returns (IngressInfo);
rpc ListIngress(ListIngressRequest) returns (ListIngressResponse);
rpc DeleteIngress(DeleteIngressRequest) returns (IngressInfo);
}
message CreateIngressRequest {
IngressInput input_type = 1;
// User provided identifier for the ingress
string name = 2;
// room to publish to
string room_name = 3;
// publish as participant
string participant_identity = 4;
// name of publishing participant (used for display only)
string participant_name = 5;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
}
enum IngressInput {
RTMP_INPUT = 0;
// FILE_INPUT = 1;
// SRT_INPUT = 2;
// URL_INPUT = 3;
}
message IngressAudioOptions {
string name = 1;
TrackSource source = 2;
// desired mime_type to publish to room
string mime_type = 3;
uint32 bitrate = 4;
bool disable_dtx = 5;
uint32 channels = 6;
}
message IngressVideoOptions {
string name = 1;
TrackSource source = 2;
// desired mime_type to publish to room
string mime_type = 3;
// simulcast layers to publish, when empty, it'll pick default simulcast
// layers at 1/2 and 1/4 of the dimensions
repeated VideoLayer layers = 4;
}
message IngressInfo {
string ingress_id = 1;
string name = 2;
string stream_key = 3;
string url = 4;
// for RTMP input, it'll be a rtmp:// URL
// for FILE input, it'll be a http:// URL
// for SRT input, it'll be a srt:// URL
IngressInput input_type = 5;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
string room_name = 8;
string participant_identity = 9;
string participant_name = 10;
bool reusable = 11;
IngressState state = 12; // Description of error/stream non compliance and debug info for publisher otherwise (received bitrate, resolution, bandwidth)
// NEXT_ID: 13
}
message IngressState {
enum Status {
ENDPOINT_INACTIVE = 0;
ENDPOINT_BUFFERING = 1;
ENDPOINT_PUBLISHING = 2;
ENDPOINT_ERROR = 3;
}
Status status = 1;
string error = 2; // Error/non compliance description if any
InputVideoState video = 3;
InputAudioState audio = 4;
string room_id = 5; // ID of the current/previous room published to
int64 started_at = 7;
repeated TrackInfo tracks = 6;
}
message InputVideoState {
uint32 mime_type = 1;
// uint32 bitrate = 2;
uint32 width = 3;
uint32 height = 4;
uint32 framerate = 5;
}
message InputAudioState {
uint32 mime_type = 1;
// uint32 bitrate = 2;
uint32 channels = 3;
uint32 sample_rate = 4;
}
message UpdateIngressRequest {
string ingress_id = 1;
string name = 2;
string room_name = 3;
string participant_identity = 4;
string participant_name = 5;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
}
message ListIngressRequest {
// when blank, lists all ingress endpoints
string room_name = 1;
}
message ListIngressResponse {
repeated IngressInfo items = 1;
}
message DeleteIngressRequest {
string ingress_id = 1;
}

View File

@ -0,0 +1,138 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
// internal protos, not exposed to clients
import "livekit_models.proto";
import "livekit_rtc.proto";
import "livekit_room.proto";
enum NodeType {
SERVER = 0;
CONTROLLER = 1;
MEDIA = 2;
TURN = 4;
}
enum NodeState {
STARTING_UP = 0;
SERVING = 1;
SHUTTING_DOWN = 2;
}
message Node {
string id = 1;
string ip = 2;
uint32 num_cpus = 3;
NodeStats stats = 4;
NodeType type = 5;
NodeState state = 6;
string region = 7;
}
message NodeStats {
// when server was started
int64 started_at = 1;
// when server last reported its status
int64 updated_at = 2;
// room
int32 num_rooms = 3;
int32 num_clients = 4;
int32 num_tracks_in = 5;
int32 num_tracks_out = 6;
// packet
uint64 bytes_in = 7;
uint64 bytes_out = 8;
uint64 packets_in = 9;
uint64 packets_out = 10;
uint64 nack_total = 11;
float bytes_in_per_sec = 12;
float bytes_out_per_sec = 13;
float packets_in_per_sec = 14;
float packets_out_per_sec = 15;
float nack_per_sec = 16;
// system
uint32 num_cpus = 17;
float load_avg_last1min = 18;
float load_avg_last5min = 19;
float load_avg_last15min = 20;
float cpu_load = 21;
uint32 sys_packets_out = 28;
uint32 sys_packets_dropped = 29;
float sys_packets_out_per_sec = 30;
float sys_packets_dropped_per_sec = 31;
float sys_packets_dropped_pct_per_sec = 32;
// retransmissions
uint64 retransmit_bytes_out = 22;
uint64 retransmit_packets_out = 23;
float retransmit_bytes_out_per_sec = 24;
float retransmit_packets_out_per_sec = 25;
// participant joins
uint64 participant_join = 26;
float participant_join_per_sec = 27;
}
// message to RTC nodes
message RTCNodeMessage {
string participant_key = 1;
int64 sender_time = 11;
string connection_id = 13;
oneof message {
StartSession start_session = 2;
SignalRequest request = 3;
// internal messages
RoomParticipantIdentity remove_participant = 4;
MuteRoomTrackRequest mute_track = 5;
UpdateParticipantRequest update_participant = 6;
DeleteRoomRequest delete_room = 7;
UpdateSubscriptionsRequest update_subscriptions = 8;
SendDataRequest send_data = 9;
UpdateRoomMetadataRequest update_room_metadata = 10;
KeepAlive keep_alive = 12;
}
}
// message to Signal nodes
message SignalNodeMessage {
string connection_id = 1;
oneof message {
SignalResponse response = 2;
EndSession end_session = 3;
}
}
message StartSession {
string room_name = 1;
string identity = 2;
string connection_id = 3;
// if a client is reconnecting (i.e. resume instead of restart)
bool reconnect = 4;
bool auto_subscribe = 9;
bool hidden = 10;
ClientInfo client = 11;
bool recorder = 12;
string name = 13;
// A user's ClaimGrants serialized in JSON
string grants_json = 14;
bool adaptive_stream = 15;
//if reconnect, client will set current sid
string participant_id = 16;
}
message EndSession {
}
message RemoveParticipant {
string participant_id = 1;
}
message KeepAlive {
}

View File

@ -0,0 +1,330 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "google/protobuf/timestamp.proto";
import "livekit_egress.proto";
message Room {
string sid = 1;
string name = 2;
uint32 empty_timeout = 3;
uint32 max_participants = 4;
int64 creation_time = 5;
string turn_password = 6;
repeated Codec enabled_codecs = 7;
string metadata = 8;
uint32 num_participants = 9;
bool active_recording = 10;
}
// room info that should not be returned to clients
message RoomInternal {
AutoTrackEgress track_egress = 1;
}
message AutoTrackEgress {
string file_prefix = 1;
oneof output {
S3Upload s3 = 2;
GCPUpload gcp = 3;
AzureBlobUpload azure = 4;
}
}
message Codec {
string mime = 1;
string fmtp_line = 2;
}
message ParticipantPermission {
// allow participant to subscribe to other tracks in the room
bool can_subscribe = 1;
// allow participant to publish new tracks to room
bool can_publish = 2;
// allow participant to publish data
bool can_publish_data = 3;
// indicates that it's hidden to others
bool hidden = 7;
// indicates it's a recorder instance
bool recorder = 8;
}
message ParticipantInfo {
enum State {
// websocket' connected, but not offered yet
JOINING = 0;
// server received client offer
JOINED = 1;
// ICE connectivity established
ACTIVE = 2;
// WS disconnected
DISCONNECTED = 3;
}
string sid = 1;
string identity = 2;
State state = 3;
repeated TrackInfo tracks = 4;
string metadata = 5;
// timestamp when participant joined room, in seconds
int64 joined_at = 6;
string name = 9;
uint32 version = 10;
ParticipantPermission permission = 11;
string region = 12;
// indicates the participant has an active publisher connection
// and can publish to the server
bool is_publisher = 13;
}
enum TrackType {
AUDIO = 0;
VIDEO = 1;
DATA = 2;
}
enum TrackSource {
UNKNOWN = 0;
CAMERA = 1;
MICROPHONE = 2;
SCREEN_SHARE = 3;
SCREEN_SHARE_AUDIO = 4;
}
message SimulcastCodecInfo {
string mime_type = 1;
string mid = 2;
string cid = 3;
repeated VideoLayer layers = 4;
}
message TrackInfo {
string sid = 1;
TrackType type = 2;
string name = 3;
bool muted = 4;
// original width of video (unset for audio)
// clients may receive a lower resolution version with simulcast
uint32 width = 5;
// original height of video (unset for audio)
uint32 height = 6;
// true if track is simulcasted
bool simulcast = 7;
// true if DTX (Discontinuous Transmission) is disabled for audio
bool disable_dtx = 8;
// source of media
TrackSource source = 9;
repeated VideoLayer layers = 10;
// mime type of codec
string mime_type = 11;
string mid = 12;
repeated SimulcastCodecInfo codecs = 13;
}
enum VideoQuality {
LOW = 0;
MEDIUM = 1;
HIGH = 2;
OFF = 3;
}
// provide information about available spatial layers
message VideoLayer {
// for tracks with a single layer, this should be HIGH
VideoQuality quality = 1;
uint32 width = 2;
uint32 height = 3;
// target bitrate, server will measure actual
uint32 bitrate = 4;
uint32 ssrc = 5;
}
// new DataPacket API
message DataPacket {
enum Kind {
RELIABLE = 0;
LOSSY = 1;
}
Kind kind = 1;
oneof value {
UserPacket user = 2;
ActiveSpeakerUpdate speaker = 3;
}
}
message ActiveSpeakerUpdate {
repeated SpeakerInfo speakers = 1;
}
message SpeakerInfo {
string sid = 1;
// audio level, 0-1.0, 1 is loudest
float level = 2;
// true if speaker is currently active
bool active = 3;
}
message UserPacket {
// participant ID of user that sent the message
string participant_sid = 1;
// user defined payload
bytes payload = 2;
// the ID of the participants who will receive the message (the message will be sent to all the people in the room if this variable is empty)
repeated string destination_sids = 3;
}
enum ConnectionQuality {
POOR = 0;
GOOD = 1;
EXCELLENT = 2;
}
message ParticipantTracks {
// participant ID of participant to whom the tracks belong
string participant_sid = 1;
repeated string track_sids = 2;
}
// details about the server
message ServerInfo {
enum Edition {
Standard = 0;
Cloud = 1;
}
Edition edition = 1;
string version = 2;
int32 protocol = 3;
string region = 4;
string node_id = 5;
// additional debugging information. sent only if server is in development mode
string debug_info = 6;
}
// details about the client
message ClientInfo {
enum SDK {
UNKNOWN = 0;
JS = 1;
SWIFT = 2;
ANDROID = 3;
FLUTTER = 4;
GO = 5;
UNITY = 6;
}
SDK sdk = 1;
string version = 2;
int32 protocol = 3;
string os = 4;
string os_version = 5;
string device_model = 6;
string browser = 7;
string browser_version = 8;
string address = 9;
// wifi, wired, cellular, vpn, empty if not known
string network = 10;
}
// server provided client configuration
message ClientConfiguration {
VideoConfiguration video = 1;
VideoConfiguration screen = 2;
ClientConfigSetting resume_connection = 3;
DisabledCodecs disabled_codecs = 4;
ClientConfigSetting force_relay = 5;
}
enum ClientConfigSetting {
UNSET = 0;
DISABLED = 1;
ENABLED = 2;
}
message VideoConfiguration {
ClientConfigSetting hardware_encoder = 1;
}
message DisabledCodecs {
repeated Codec codecs = 1;
}
enum DisconnectReason {
UNKNOWN_REASON = 0;
CLIENT_INITIATED = 1;
DUPLICATE_IDENTITY = 2;
SERVER_SHUTDOWN = 3;
PARTICIPANT_REMOVED = 4;
ROOM_DELETED = 5;
STATE_MISMATCH = 6;
JOIN_FAILURE = 7;
}
message RTPStats {
google.protobuf.Timestamp start_time = 1;
google.protobuf.Timestamp end_time = 2;
double duration = 3;
uint32 packets = 4;
double packet_rate = 5;
uint64 bytes = 6;
uint64 header_bytes = 39;
double bitrate = 7;
uint32 packets_lost = 8;
double packet_loss_rate = 9;
float packet_loss_percentage = 10;
uint32 packets_duplicate = 11;
double packet_duplicate_rate = 12;
uint64 bytes_duplicate = 13;
uint64 header_bytes_duplicate = 40;
double bitrate_duplicate = 14;
uint32 packets_padding = 15;
double packet_padding_rate = 16;
uint64 bytes_padding = 17;
uint64 header_bytes_padding = 41;
double bitrate_padding = 18;
uint32 packets_out_of_order = 19;
uint32 frames = 20;
double frame_rate = 21;
double jitter_current = 22;
double jitter_max = 23;
map<int32, uint32> gap_histogram = 24;
uint32 nacks = 25;
uint32 nack_acks = 37;
uint32 nack_misses = 26;
uint32 nack_repeated = 38;
uint32 plis = 27;
google.protobuf.Timestamp last_pli = 28;
uint32 firs = 29;
google.protobuf.Timestamp last_fir = 30;
uint32 rtt_current = 31;
uint32 rtt_max = 32;
uint32 key_frames = 33;
google.protobuf.Timestamp last_key_frame = 34;
uint32 layer_lock_plis = 35;
google.protobuf.Timestamp last_layer_lock_pli = 36;
}
message TimedVersion {
int64 unix_micro = 1;
int32 ticks = 2;
}

View File

@ -0,0 +1,159 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_models.proto";
import "livekit_egress.proto";
// Room service that can be performed on any node
// they are Twirp-based HTTP req/responses
service RoomService {
// Creates a room with settings. Requires `roomCreate` permission.
// This method is optional; rooms are automatically created when clients connect to them for the first time.
rpc CreateRoom(CreateRoomRequest) returns (Room);
// List rooms that are active on the server. Requires `roomList` permission.
rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse);
// Deletes an existing room by name or id. Requires `roomCreate` permission.
// DeleteRoom will disconnect all participants that are currently in the room.
rpc DeleteRoom(DeleteRoomRequest) returns (DeleteRoomResponse);
// Lists participants in a room, Requires `roomAdmin`
rpc ListParticipants(ListParticipantsRequest) returns (ListParticipantsResponse);
// Get information on a specific participant, Requires `roomAdmin`
rpc GetParticipant(RoomParticipantIdentity) returns (ParticipantInfo);
// Removes a participant from room. Requires `roomAdmin`
rpc RemoveParticipant(RoomParticipantIdentity) returns (RemoveParticipantResponse);
// Mute/unmute a participant's track, Requires `roomAdmin`
rpc MutePublishedTrack(MuteRoomTrackRequest) returns (MuteRoomTrackResponse);
// Update participant metadata, will cause updates to be broadcasted to everyone in the room. Requires `roomAdmin`
rpc UpdateParticipant(UpdateParticipantRequest) returns (ParticipantInfo);
// Subscribes or unsubscribe a participant from tracks. Requires `roomAdmin`
rpc UpdateSubscriptions(UpdateSubscriptionsRequest) returns (UpdateSubscriptionsResponse);
// Send data over data channel to participants in a room, Requires `roomAdmin`
rpc SendData(SendDataRequest) returns (SendDataResponse);
// Update room metadata, will cause updates to be broadcasted to everyone in the room, Requires `roomAdmin`
rpc UpdateRoomMetadata (UpdateRoomMetadataRequest) returns (Room);
}
message CreateRoomRequest {
// name of the room
string name = 1;
// number of seconds to keep the room open if no one joins
uint32 empty_timeout = 2;
// limit number of participants that can be in a room
uint32 max_participants = 3;
// override the node room is allocated to, for debugging
string node_id = 4;
// metadata of room
string metadata = 5;
// egress
RoomEgress egress = 6;
}
message RoomEgress {
RoomCompositeEgressRequest room = 1;
AutoTrackEgress tracks = 2;
}
message ListRoomsRequest {
// when set, will only return rooms with name match
repeated string names = 1;
}
message ListRoomsResponse {
repeated Room rooms = 1;
}
message DeleteRoomRequest {
// name of the room
string room = 1;
}
message DeleteRoomResponse {
}
message ListParticipantsRequest {
// name of the room
string room = 1;
}
message ListParticipantsResponse {
repeated ParticipantInfo participants = 1;
}
message RoomParticipantIdentity {
// name of the room
string room = 1;
// identity of the participant
string identity = 2;
}
message RemoveParticipantResponse {
}
message MuteRoomTrackRequest {
// name of the room
string room = 1;
string identity = 2;
// sid of the track to mute
string track_sid = 3;
// set to true to mute, false to unmute
bool muted = 4;
}
message MuteRoomTrackResponse {
TrackInfo track = 1;
}
message UpdateParticipantRequest {
string room = 1;
string identity = 2;
// metadata to update. skipping updates if left empty
string metadata = 3;
// set to update the participant's permissions
ParticipantPermission permission = 4;
}
message UpdateSubscriptionsRequest {
string room = 1;
string identity = 2;
// list of sids of tracks
repeated string track_sids = 3;
// set to true to subscribe, false to unsubscribe from tracks
bool subscribe = 4;
// list of participants and their tracks
repeated ParticipantTracks participant_tracks = 5;
}
message UpdateSubscriptionsResponse {
// empty for now
}
message SendDataRequest {
string room = 1;
bytes data = 2;
DataPacket.Kind kind = 3;
repeated string destination_sids = 4;
}
message SendDataResponse {
//
}
message UpdateRoomMetadataRequest {
string room = 1;
// metadata to update. skipping updates if left empty
string metadata = 2;
}

View File

@ -0,0 +1,83 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_egress.proto";
import "livekit_ingress.proto";
message StartEgressRequest {
// request metadata
string egress_id = 1;
string request_id = 2;
string sender_id = 10;
int64 sent_at = 4;
// request
oneof request {
RoomCompositeEgressRequest room_composite = 5;
TrackCompositeEgressRequest track_composite = 6;
TrackEgressRequest track = 7;
}
// connection info
string room_id = 3;
string token = 8;
string ws_url = 9;
}
message EgressRequest {
// request metadata
string egress_id = 1;
string request_id = 2;
string sender_id = 5;
// request
oneof request {
UpdateStreamRequest update_stream = 3;
StopEgressRequest stop = 4;
}
}
message EgressResponse {
EgressInfo info = 1;
string error = 2;
string request_id = 3;
}
message IngressRequest {
// request metadata
string ingress_id = 1;
string request_id = 2;
string sender_id = 3;
oneof request {
UpdateIngressRequest update = 4;
DeleteIngressRequest delete = 5;
}
}
// Query an ingress info from an ingress ID or stream key
message GetIngressInfoRequest {
string ingress_id = 1;
string stream_key = 2;
string request_id = 3;
string sender_id = 4;
int64 sent_at = 5;
}
message IngressResponse {
IngressInfo info = 1;
string error = 2;
string request_id = 3;
}
message GetIngressInfoResponse {
IngressInfo info = 1;
string token = 2;
string ws_url = 3;
string error = 4;
string request_id = 5;
}

View File

@ -0,0 +1,301 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_models.proto";
message SignalRequest {
oneof message {
// initial join exchange, for publisher
SessionDescription offer = 1;
// participant answering publisher offer
SessionDescription answer = 2;
TrickleRequest trickle = 3;
AddTrackRequest add_track = 4;
// mute the participant's published tracks
MuteTrackRequest mute = 5;
// Subscribe or unsubscribe from tracks
UpdateSubscription subscription = 6;
// Update settings of subscribed tracks
UpdateTrackSettings track_setting = 7;
// Immediately terminate session
LeaveRequest leave = 8;
// Set active published layers, deprecated in favor of automatic tracking
// SetSimulcastLayers simulcast = 9;
// Update published video layers
UpdateVideoLayers update_layers = 10;
// Update subscriber permissions
SubscriptionPermission subscription_permission = 11;
// sync client's subscribe state to server during reconnect
SyncState sync_state = 12;
// Simulate conditions, for client validations
SimulateScenario simulate = 13;
// client triggered ping to server
int64 ping = 14;
}
}
message SignalResponse {
oneof message {
// sent when join is accepted
JoinResponse join = 1;
// sent when server answers publisher
SessionDescription answer = 2;
// sent when server is sending subscriber an offer
SessionDescription offer = 3;
// sent when an ICE candidate is available
TrickleRequest trickle = 4;
// sent when participants in the room has changed
ParticipantUpdate update = 5;
// sent to the participant when their track has been published
TrackPublishedResponse track_published = 6;
// Immediately terminate session
LeaveRequest leave = 8;
// server initiated mute
MuteTrackRequest mute = 9;
// indicates changes to speaker status, including when they've gone to not speaking
SpeakersChanged speakers_changed = 10;
// sent when metadata of the room has changed
RoomUpdate room_update = 11;
// when connection quality changed
ConnectionQualityUpdate connection_quality = 12;
// when streamed tracks state changed, used to notify when any of the streams were paused due to
// congestion
StreamStateUpdate stream_state_update = 13;
// when max subscribe quality changed, used by dynamic broadcasting to disable unused layers
SubscribedQualityUpdate subscribed_quality_update = 14;
// when subscription permission changed
SubscriptionPermissionUpdate subscription_permission_update = 15;
// update the token the client was using, to prevent an active client from using an expired token
string refresh_token = 16;
// server initiated track unpublish
TrackUnpublishedResponse track_unpublished = 17;
// respond to ping
int64 pong = 18;
}
}
enum SignalTarget {
PUBLISHER = 0;
SUBSCRIBER = 1;
}
message SimulcastCodec {
string codec = 1;
string cid = 2;
bool enable_simulcast_layers = 3;
}
message AddTrackRequest {
// client ID of track, to match it when RTC track is received
string cid = 1;
string name = 2;
TrackType type = 3;
// to be deprecated in favor of layers
uint32 width = 4;
uint32 height = 5;
// true to add track and initialize to muted
bool muted = 6;
// true if DTX (Discontinuous Transmission) is disabled for audio
bool disable_dtx = 7;
TrackSource source = 8;
repeated VideoLayer layers = 9;
repeated SimulcastCodec simulcast_codecs = 10;
// server ID of track, publish new codec to exist track
string sid = 11;
}
message TrickleRequest {
string candidateInit = 1;
SignalTarget target = 2;
}
message MuteTrackRequest {
string sid = 1;
bool muted = 2;
}
message JoinResponse {
Room room = 1;
ParticipantInfo participant = 2;
repeated ParticipantInfo other_participants = 3;
// deprecated. use server_info.version instead.
string server_version = 4;
repeated ICEServer ice_servers = 5;
// use subscriber as the primary PeerConnection
bool subscriber_primary = 6;
// when the current server isn't available, return alternate url to retry connection
// when this is set, the other fields will be largely empty
string alternative_url = 7;
ClientConfiguration client_configuration = 8;
// deprecated. use server_info.region instead.
string server_region = 9;
int32 ping_timeout = 10;
int32 ping_interval = 11;
ServerInfo server_info = 12;
}
message TrackPublishedResponse {
string cid = 1;
TrackInfo track = 2;
}
message TrackUnpublishedResponse {
string track_sid = 1;
}
message SessionDescription {
string type = 1; // "answer" | "offer" | "pranswer" | "rollback"
string sdp = 2;
}
message ParticipantUpdate {
repeated ParticipantInfo participants = 1;
}
message UpdateSubscription {
repeated string track_sids = 1;
bool subscribe = 2;
repeated ParticipantTracks participant_tracks = 3;
}
message UpdateTrackSettings {
repeated string track_sids = 1;
// when true, the track is placed in a paused state, with no new data returned
bool disabled = 3;
// deprecated in favor of width & height
VideoQuality quality = 4;
// for video, width to receive
uint32 width = 5;
// for video, height to receive
uint32 height = 6;
}
message LeaveRequest {
// sent when server initiates the disconnect due to server-restart
// indicates clients should attempt full-reconnect sequence
bool can_reconnect = 1;
DisconnectReason reason = 2;
}
// message to indicate published video track dimensions are changing
message UpdateVideoLayers {
string track_sid = 1;
repeated VideoLayer layers = 2;
}
message ICEServer {
repeated string urls = 1;
string username = 2;
string credential = 3;
}
message SpeakersChanged {
repeated SpeakerInfo speakers = 1;
}
message RoomUpdate {
Room room = 1;
}
message ConnectionQualityInfo {
string participant_sid = 1;
ConnectionQuality quality = 2;
float score = 3;
}
message ConnectionQualityUpdate {
repeated ConnectionQualityInfo updates = 1;
}
enum StreamState {
ACTIVE = 0;
PAUSED = 1;
}
message StreamStateInfo {
string participant_sid = 1;
string track_sid = 2;
StreamState state = 3;
}
message StreamStateUpdate {
repeated StreamStateInfo stream_states = 1;
}
message SubscribedQuality {
VideoQuality quality = 1;
bool enabled = 2;
}
message SubscribedCodec {
string codec = 1;
repeated SubscribedQuality qualities = 2;
}
message SubscribedQualityUpdate {
string track_sid = 1;
repeated SubscribedQuality subscribed_qualities = 2;
repeated SubscribedCodec subscribed_codecs = 3;
}
message TrackPermission {
// permission could be granted either by participant sid or identity
string participant_sid = 1;
bool all_tracks = 2;
repeated string track_sids = 3;
string participant_identity = 4;
}
message SubscriptionPermission {
bool all_participants = 1;
repeated TrackPermission track_permissions = 2;
}
message SubscriptionPermissionUpdate {
string participant_sid = 1;
string track_sid = 2;
bool allowed = 3;
}
message SyncState {
// last subscribe answer before reconnecting
SessionDescription answer = 1;
UpdateSubscription subscription = 2;
repeated TrackPublishedResponse publish_tracks = 3;
repeated DataChannelInfo data_channels = 4;
// last received server side offer before reconnecting
SessionDescription offer = 5;
}
message DataChannelInfo {
string label = 1;
uint32 id = 2;
SignalTarget target = 3;
}
enum CandidateProtocol {
UDP = 0;
TCP = 1;
TLS = 2;
}
message SimulateScenario {
oneof scenario {
// simulate N seconds of speaker activity
int32 speaker_update = 1;
// simulate local node failure
bool node_failure = 2;
// simulate migration
bool migration = 3;
// server to send leave
bool server_leave = 4;
// switch candidate protocol to tcp
CandidateProtocol switch_candidate_protocol = 5;
}
}

View File

@ -0,0 +1,36 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_models.proto";
import "livekit_egress.proto";
import "livekit_ingress.proto";
message WebhookEvent {
// one of room_started, room_finished, participant_joined, participant_left,
// track_published, track_unpublished, egress_started, egress_updated, egress_ended, ingress_started, ingress_ended
string event = 1;
Room room = 2;
// set when event is participant_* or track_*
ParticipantInfo participant = 3;
// set when event is egress_*
EgressInfo egress_info = 9;
// set when event is ingress_*
IngressInfo ingress_info = 10;
// set when event is track_*
TrackInfo track = 8;
// unique event uuid
string id = 6;
// timestamp in seconds
int64 created_at = 7;
}