syntax = "proto3";

package soniox.speech_service;

import "google/protobuf/timestamp.proto";

service SpeechService {
  // Synchronous transcription
  rpc Transcribe(TranscribeRequest) returns (TranscribeResponse) {}
  rpc TranscribeStream(stream TranscribeStreamRequest) returns (stream TranscribeStreamResponse) {}
  rpc TranscribeMeeting(stream TranscribeMeetingRequest) returns (stream TranscribeMeetingResponse) {}

  // Asynchronous transcription
  rpc TranscribeAsync(stream TranscribeAsyncRequest) returns (TranscribeAsyncResponse) {}
  rpc GetTranscribeAsyncStatus(GetTranscribeAsyncStatusRequest) returns (GetTranscribeAsyncStatusResponse) {}
  rpc GetTranscribeAsyncResult(GetTranscribeAsyncResultRequest) returns (stream GetTranscribeAsyncResultResponse) {}
  rpc DeleteTranscribeAsyncFile(DeleteTranscribeAsyncFileRequest) returns (DeleteTranscribeAsyncFileResponse) {}

  // Speech context
  rpc CreateSpeechContext(CreateSpeechContextRequest) returns (CreateSpeechContextResponse) {}
  rpc DeleteSpeechContext(DeleteSpeechContextRequest) returns (DeleteSpeechContextResponse) {}
  rpc ListSpeechContextNames(ListSpeechContextNamesRequest) returns (ListSpeechContextNamesResponse) {}
  rpc GetSpeechContext(GetSpeechContextRequest) returns (GetSpeechContextResponse) {}
  rpc UpdateSpeechContext(UpdateSpeechContextRequest) returns (UpdateSpeechContextResponse) {}

  // Speaker AI
  rpc AddSpeaker(AddSpeakerRequest) returns (AddSpeakerResponse) {}
  rpc GetSpeaker(GetSpeakerRequest) returns (GetSpeakerResponse) {}
  rpc RemoveSpeaker(RemoveSpeakerRequest) returns (RemoveSpeakerResponse) {}
  rpc ListSpeakers(ListSpeakersRequest) returns (ListSpeakersResponse) {}
  rpc AddSpeakerAudio(AddSpeakerAudioRequest) returns (AddSpeakerAudioResponse) {}
  rpc GetSpeakerAudio(GetSpeakerAudioRequest) returns (GetSpeakerAudioResponse) {}
  rpc RemoveSpeakerAudio(RemoveSpeakerAudioRequest) returns (RemoveSpeakerAudioResponse) {}

  // Storage
  rpc Search(SearchRequest) returns (SearchResponse) {}
  rpc GetObject(GetObjectRequest) returns (GetObjectResponse) {}
  rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse) {}
  rpc DeleteObject(DeleteObjectRequest) returns (DeleteObjectResponse) {}
  rpc GetAudio(GetAudioRequest) returns (stream GetAudioResponse) {}

  // Temporary API key
  rpc CreateTemporaryApiKey(CreateTemporaryApiKeyRequest) returns (CreateTemporaryApiKeyResponse) {}
}

// Transcribe

message TranscribeRequest {
  string api_key = 1;
  TranscriptionConfig config = 4;
  bytes audio = 3;
}

message TranscribeResponse {
  Result result = 1;
  repeated Result channel_results = 2;
  TranscriptionMetadata metadata = 3;
}

// TranscribeStream

message TranscribeStreamRequest {
  string api_key = 1;
  TranscriptionConfig config = 4;
  bytes audio = 3;
}

message TranscribeStreamResponse {
  Result result = 1;
  TranscriptionMetadata metadata = 2;
}

// TranscribeMeeting

message TranscribeMeetingRequest {
  string api_key = 1;
  TranscriptionConfig config = 10;
  int32 seq_num = 3;
  int32 stream_id = 4;
  bool start_of_segment = 5;
  bytes audio = 6;
  bool end_of_segment = 7;
}

message TranscribeMeetingResponse {
  int32 seq_num = 1;
  int32 stream_id = 2;
  bool start_of_segment = 3;
  bool end_of_segment = 4;
  Result result = 5;
  string error = 6;
  TranscriptionMetadata metadata = 7;
}

// TranscribeAsync

message TranscribeAsyncRequest {
  string api_key = 1;
  string reference_name = 3;
  TranscriptionConfig config = 5;
  bool enable_eof = 6;
  bool eof = 7;
  bytes audio = 4;
}
message TranscribeAsyncResponse {
  string file_id = 1;
}

// GetTranscribeAsyncStatus

message GetTranscribeAsyncStatusRequest {
  string api_key = 1;
  string file_id = 2;
}

message GetTranscribeAsyncStatusResponse {
  repeated TranscribeAsyncFileStatus files = 1;
}

message TranscribeAsyncFileStatus {
  string file_id = 1;
  string reference_name = 2;
  string status = 3; // one of: QUEUED, TRANSCRIBING, COMPLETED, FAILED
  google.protobuf.Timestamp created_time = 4;
  string error_message = 5;
}

// GetTranscribeAsyncResult

message GetTranscribeAsyncResultRequest {
  string api_key = 1;
  string file_id = 2;
}

message GetTranscribeAsyncResultResponse {
  bool separate_recognition_per_channel = 2;
  Result result = 1;
  TranscriptionMetadata metadata = 3;
}

// DeleteTranscribeAsyncFile

message DeleteTranscribeAsyncFileRequest {
  string api_key = 1;
  string file_id = 2;
}

message DeleteTranscribeAsyncFileResponse {
}

// Common

message TranscriptionConfig {
  // Optional field to enable the client to identify the transcription
  // request in API logs.
  string client_request_reference = 19;

  // Input options
  string audio_format = 1;
  int32 sample_rate_hertz = 2;
  int32 num_audio_channels = 3;

  // Output options
  bool include_nonfinal = 4;
  bool enable_separate_recognition_per_channel = 16;
  bool enable_endpoint_detection = 18;

  // Speech adaptation
  SpeechContext speech_context = 5;

  // Content moderation
  bool enable_profanity_filter = 6;
  repeated string content_moderation_phrases = 7;

  // Speaker diarization
  bool enable_streaming_speaker_diarization = 8;
  bool enable_global_speaker_diarization = 9;
  int32 min_num_speakers = 10;
  int32 max_num_speakers = 11;

  // Speaker identification
  bool enable_speaker_identification = 12;
  repeated string cand_speaker_names = 13;

  // Model options
  string model = 14;
  bool enable_dictation = 15;

  // Storage and Search options
  StorageConfig storage_config = 1006;
}

message TranscriptionMetadata {
  string package_version = 1;
}

message Result {
  repeated Word words = 1;
  int32 final_proc_time_ms = 2;
  int32 total_proc_time_ms = 3;
  repeated ResultSpeaker speakers = 6;
  int32 channel = 7;
}

message Word {
  string text = 1;
  int32 start_ms = 2;
  int32 duration_ms = 3;
  bool is_final = 4;
  int32 speaker = 5;
  string orig_text = 8;
  double confidence = 9;
}

message ResultSpeaker {
  int32 speaker = 1;
  string name = 2;
}

// SpeechContext

message SpeechContext {
  repeated SpeechContextEntry entries = 1;
  string name = 2;
}

message SpeechContextEntry {
  repeated string phrases = 1;
  double boost = 2;
}

message CreateSpeechContextRequest {
  string api_key = 1;
  SpeechContext speech_context = 2;
}
message CreateSpeechContextResponse {
}

message DeleteSpeechContextRequest {
  string api_key = 1;
  string name = 2;
}
message DeleteSpeechContextResponse {
}

message ListSpeechContextNamesRequest {
  string api_key = 1;
}
message ListSpeechContextNamesResponse {
  repeated string names = 1;
}

message GetSpeechContextRequest {
  string api_key = 1;
  string name = 2;
}
message GetSpeechContextResponse {
  SpeechContext speech_context = 1;
}

message UpdateSpeechContextRequest {
  string api_key = 1;
  SpeechContext speech_context = 2;
}
message UpdateSpeechContextResponse {
}

// Speaker AI

// AddSpeaker

message AddSpeakerRequest {
  string api_key = 1;
  string name = 2;
}

message AddSpeakerResponse {
  string name = 1;
  google.protobuf.Timestamp created = 2;
}

// GetSpeaker

message GetSpeakerRequest {
  string api_key = 1;
  string name = 2;
}

message GetSpeakerResponse {
  string name = 1;
  google.protobuf.Timestamp created = 2;
  repeated GetSpeakerResponseAudio audios = 3;
}

message GetSpeakerResponseAudio {
  string audio_name = 1;
  google.protobuf.Timestamp created = 2;
  int32 duration_ms = 3;
}

// RemoveSpeaker

message RemoveSpeakerRequest {
  string api_key = 1;
  string name = 2;
}

message RemoveSpeakerResponse {}

// ListSpeakers

message ListSpeakersRequest {
  string api_key = 1;
}

message ListSpeakersResponse {
  repeated ListSpeakersResponseSpeaker speakers = 1;
}

message ListSpeakersResponseSpeaker {
  string name = 1;
  google.protobuf.Timestamp created = 2;
  int32 num_audios = 3;
}

// AddSpeakerAudio

message AddSpeakerAudioRequest {
  string api_key = 1;
  string speaker_name = 2;
  string audio_name = 3;
  bytes audio = 4;
}

message AddSpeakerAudioResponse {
  string speaker_name = 1;
  string audio_name = 2;
  google.protobuf.Timestamp created = 3;
  int32 duration_ms = 4;
}

// GetSpeakerAudio

message GetSpeakerAudioRequest {
  string api_key = 1;
  string speaker_name = 2;
  string audio_name = 3;
}

message GetSpeakerAudioResponse {
  string speaker_name = 1;
  string audio_name = 2;
  google.protobuf.Timestamp created = 3;
  int32 duration_ms = 4;
  bytes audio = 5;
}

// RemoveSpeakerAudio

message RemoveSpeakerAudioRequest {
  string api_key = 1;
  string speaker_name = 2;
  string audio_name = 3;
}

message RemoveSpeakerAudioResponse {}

// Storage

message StorageConfig {
  string object_id = 1;
  map<string, string> metadata = 2;
  string title = 3;
  google.protobuf.Timestamp datetime = 4;
  bool disable_store_audio = 5;
  bool disable_store_transcript = 6;
}

message Token {
  int32 idx = 1;
  int32 text_start = 2;
  int32 text_end = 3;
  // Spoken text.
  string text = 4;
  int32 start_ms = 5;
  int32 duration_ms = 6;
  double confidence = 7;
  int32 speaker_id = 8;
  bool profane = 9;
}

message Sentence {
  int32 token_start = 1;
  int32 token_end = 2;
}

message Paragraph {
  int32 sentence_start = 1;
  int32 sentence_end = 2;
}

message Keyterm {
  string text = 1;
  double score = 2;
  repeated int32 token_start_indexes = 3;
}

message Transcript {
  string text = 1;
  repeated Token tokens = 2;
  repeated Sentence sentences = 3;
  repeated Paragraph paragraphs = 4;
  repeated Keyterm keyterms = 6;
  map<int32, string> speaker_names = 7;
}

message StoredObject {
  string object_id = 1;
  map<string, string> metadata = 2;
  string title = 3;
  google.protobuf.Timestamp datetime = 4;
  google.protobuf.Timestamp stored_datetime = 5;
  int32 duration_ms = 6;
  int32 num_audio_channels = 10;
  bool audio_stored = 11;
  Transcript transcript = 7;
}

// Search

message SearchRequest {
  string api_key = 1;
  string object_id = 2;
  string metadata_query = 3;
  google.protobuf.Timestamp datetime_from = 4;
  google.protobuf.Timestamp datetime_to = 5;
  string text_query = 6;
  int32 start = 7;
  int32 num = 8;
}

message SearchResult {
  string object_id = 1;
  map<string, string> metadata = 2;
  string title = 3;
  google.protobuf.Timestamp datetime = 4;
  int32 duration_ms = 5;
  string preview = 6;
}

message SearchResponse {
  int32 num_found = 1;
  int32 start = 2;
  repeated SearchResult results = 3;
}

// GetObject

message GetObjectRequest {
  string api_key = 1;
  string object_id = 2;
}

message GetObjectResponse {
  StoredObject object = 1;
}

// ListObjects

message ListObjectsRequest {
  string api_key = 1;
  google.protobuf.Timestamp stored_datetime_from = 2;
  google.protobuf.Timestamp stored_datetime_to = 3;
  int64 start = 4;
  int64 num = 5;
}

message ListObjectsResponse {
  int64 start = 1;
  repeated ListObjectsResponseObject objects = 2;
}

message ListObjectsResponseObject {
  string object_id = 1;
  google.protobuf.Timestamp stored_datetime = 2;
  bool audio_stored = 3;
  bool transcript_stored = 4;
  int32 audio_duration_ms = 5;
  int32 stored_audio_ms = 6;
}

// DeleteObject

message DeleteObjectRequest {
  string api_key = 1;
  string object_id = 2;
}

message DeleteObjectResponse {}

// GetAudio

message GetAudioRequest {
  message TimeSegment {
    int32 start_ms = 1;
    int32 duration_ms = 2;
  }

  message TokenSegment {
    int32 token_start = 1;
    int32 token_end = 2;
  }

  string api_key = 1;
  string object_id = 2;
  oneof oneof_segment {
    TimeSegment time_segment = 3;
    TokenSegment token_segment = 4;
  }
  string audio_bytes_format = 5;
}

message GetAudioResponse {
  string object_id = 1;
  int32 start_ms = 2;
  int32 duration_ms = 3;
  int32 total_duration_ms = 4;
  int32 num_audio_channels = 6;
  bytes data = 5;
}

// CreateTemporaryApiKey

message CreateTemporaryApiKeyRequest {
  string api_key = 1;
  string usage_type = 2;
  int32 expires_in_s = 4;
  string client_request_reference = 3;
}

message CreateTemporaryApiKeyResponse {
  string key = 1;
  google.protobuf.Timestamp expires_datetime = 2;
}
