// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

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 Egress {
  // start recording or streaming a room, participant, or tracks
  rpc StartRoomCompositeEgress(RoomCompositeEgressRequest) returns (EgressInfo);
  rpc StartWebEgress(WebEgressRequest) returns (EgressInfo);
  rpc StartParticipantEgress(ParticipantEgressRequest) 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;   // template base url (default https://recorder.livekit.io)
  oneof output {                // deprecated (use _output fields)
    EncodedFileOutput file = 6 [deprecated = true];
    StreamOutput stream = 7 [deprecated = true];
    SegmentedFileOutput segments = 10 [deprecated = true];
  }
  oneof options {
    EncodingOptionsPreset preset = 8; // (default H264_720P_30)
    EncodingOptions advanced = 9;     // (optional)
  }
  repeated EncodedFileOutput file_outputs = 11;
  repeated StreamOutput stream_outputs = 12;
  repeated SegmentedFileOutput segment_outputs = 13;
  repeated ImageOutput image_outputs = 14;
}

// record any website
message WebEgressRequest {
  string url = 1;
  bool audio_only = 2;
  bool video_only = 3;
  bool await_start_signal = 12;
  oneof output { // deprecated (use _output fields)
    EncodedFileOutput file = 4 [deprecated = true];
    StreamOutput stream = 5 [deprecated = true];
    SegmentedFileOutput segments = 6 [deprecated = true];
  }
  oneof options {
    EncodingOptionsPreset preset = 7;
    EncodingOptions advanced = 8;
  }
  repeated EncodedFileOutput file_outputs = 9;
  repeated StreamOutput stream_outputs = 10;
  repeated SegmentedFileOutput segment_outputs = 11;
  repeated ImageOutput image_outputs = 13;
}

// record audio and video from a single participant
message ParticipantEgressRequest {
  string room_name = 1;  // required
  string identity = 2;   // required
  bool screen_share = 3; // (default false)
  oneof options {
    EncodingOptionsPreset preset = 4; // (default H264_720P_30)
    EncodingOptions advanced = 5;     // (optional)
  }
  repeated EncodedFileOutput file_outputs = 6;
  repeated StreamOutput stream_outputs = 7;
  repeated SegmentedFileOutput segment_outputs = 8;
  repeated ImageOutput image_outputs = 9;
}

// 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 {             // deprecated (use _output fields)
    EncodedFileOutput file = 4 [deprecated = true];
    StreamOutput stream = 5 [deprecated = true];
    SegmentedFileOutput segments = 8 [deprecated = true];
  }
  oneof options {
    EncodingOptionsPreset preset = 6; // (default H264_720P_30)
    EncodingOptions advanced = 7;     // (optional)
  }
  repeated EncodedFileOutput file_outputs = 11;
  repeated StreamOutput stream_outputs = 12;
  repeated SegmentedFileOutput segment_outputs = 13;
  repeated ImageOutput image_outputs = 14;
}

// 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;           // see egress docs for templating (default {room_name}-{time})
  bool disable_manifest = 6;     // disable upload of manifest file (default false)
  oneof output {
    S3Upload s3 = 3;
    GCPUpload gcp = 4;
    AzureBlobUpload azure = 5;
    AliOSSUpload aliOSS = 7;
  }
}

enum SegmentedFileProtocol {
  DEFAULT_SEGMENTED_FILE_PROTOCOL = 0;
  HLS_PROTOCOL = 1;
}

enum SegmentedFileSuffix {
  INDEX = 0;
  TIMESTAMP = 1;
}

// 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)
  string live_playlist_name = 11;           // (optional, disabled if not provided). Path of a live playlist
  uint32 segment_duration = 4;              // in seconds (optional)
  SegmentedFileSuffix filename_suffix = 10; // (optional, default INDEX)
  bool disable_manifest = 8;                // disable upload of manifest file (default false)
  oneof output {                            // required
    S3Upload s3 = 5;
    GCPUpload gcp = 6;
    AzureBlobUpload azure = 7;
    AliOSSUpload aliOSS = 9;
  }
}

message DirectFileOutput {
  string filepath = 1;       // see egress docs for templating (default {track_id}-{time})
  bool disable_manifest = 5; // disable upload of manifest file (default false)
  oneof output {
    S3Upload s3 = 2;
    GCPUpload gcp = 3;
    AzureBlobUpload azure = 4;
    AliOSSUpload aliOSS = 6;
  }
}

enum ImageFileSuffix {
  IMAGE_SUFFIX_INDEX = 0;
  IMAGE_SUFFIX_TIMESTAMP = 1;
}

message ImageOutput {
  uint32 capture_interval = 1;              // in seconds (required)
  int32 width = 2;                          // (optional, defaults to track width)
  int32 height = 3;                         // (optional, defaults to track height)
  string filename_prefix = 4;               // (optional)
  ImageFileSuffix filename_suffix = 5;      // (optional, default INDEX)
  ImageCodec image_codec = 6;               // (optional)
  bool disable_manifest = 7;                // disable upload of manifest file (default false)
  oneof output {                            // required
    S3Upload s3 = 8;
    GCPUpload gcp = 9;
    AzureBlobUpload azure = 10;
    AliOSSUpload aliOSS = 11;
  }
}

message S3Upload {
  string access_key = 1;
  string secret = 2;
  string region = 3;
  string endpoint = 4;
  string bucket = 5;
  bool force_path_style = 6;
  map<string, string> metadata = 7;
  string tagging = 8;
  // Content-Disposition header
  string content_disposition = 9;
}

message GCPUpload {
  // service account credentials serialized in JSON "credentials.json"
  string credentials = 1;
  string bucket = 2;
}

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

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

enum StreamProtocol {
  DEFAULT_PROTOCOL = 0; // protocol chosen based on urls
  RTMP = 1;
}

message StreamOutput {
  StreamProtocol protocol = 1; // required
  repeated string urls = 2;    // required
}

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_quality = 11;       // quality setting on audio encoder
  int32 audio_frequency = 7;      // (default 44100)
  VideoCodec video_codec = 8;     // (default H264_MAIN)
  int32 video_bitrate = 9;        // (default 4500)
  int32 video_quality = 12;       // quality setting on video encoder
  double key_frame_interval = 10; // in seconds (default 4s for streaming, segment duration for segmented output, encoder default for files)
}

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, filter by room name)
  string egress_id = 2; // (optional, filter by egress ID)
  bool active = 3;      // (optional, list active egress only)
}

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;
  int64 updated_at = 18;
  string error = 9;
  oneof request {
    RoomCompositeEgressRequest room_composite = 4;
    WebEgressRequest web = 14;
    ParticipantEgressRequest participant = 19;
    TrackCompositeEgressRequest track_composite = 5;
    TrackEgressRequest track = 6;
  }
  oneof result { // deprecated (use _result fields)
    StreamInfoList stream = 7 [deprecated = true];
    FileInfo file = 8 [deprecated = true];
    SegmentsInfo segments = 12 [deprecated = true];
  }
  repeated StreamInfo stream_results = 15;
  repeated FileInfo file_results = 16;
  repeated SegmentsInfo segment_results = 17;
  repeated ImagesInfo image_results = 20;

  // next ID: 21
}

message StreamInfoList {
  option deprecated = true;
  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;
  string error = 6;
}

message FileInfo {
  string filename = 1;
  int64 started_at = 2;
  int64 ended_at = 3;
  int64 duration = 6;
  int64 size = 4;
  string location = 5;
}

message SegmentsInfo {
  string playlist_name = 1;
  string live_playlist_name = 8;
  int64 duration = 2;
  int64 size = 3;
  string playlist_location = 4;
  string live_playlist_location = 9;
  int64 segment_count = 5;
  int64 started_at = 6;
  int64 ended_at = 7;
}

message ImagesInfo {
  int64 image_count = 1;
  int64 started_at = 2;
  int64 ended_at = 3;
}

message AutoParticipantEgress {
  oneof options {
    EncodingOptionsPreset preset = 1; // (default H264_720P_30)
    EncodingOptions advanced = 2;     // (optional)
  }
  repeated EncodedFileOutput file_outputs = 3;
  repeated SegmentedFileOutput segment_outputs = 4;
}

message AutoTrackEgress {
  string filepath = 1;       // see docs for templating (default {track_id}-{time})
  bool disable_manifest = 5; // disables upload of json manifest file (default false)
  oneof output {
    S3Upload s3 = 2;
    GCPUpload gcp = 3;
    AzureBlobUpload azure = 4;
  }
}
