openai_protocol/transcription.rs
1//! Audio transcription API protocol definitions.
2//!
3//! This module defines the request type for the OpenAI-compatible
4//! `/v1/audio/transcriptions` endpoint. The wire format is
5//! `multipart/form-data` (an audio file plus text form fields), so the
6//! struct below carries only the non-file fields; the file bytes travel
7//! through the router as a separate payload.
8
9use serde::{Deserialize, Serialize};
10
11use super::common::GenerationRequest;
12
13/// Transcription request - compatible with OpenAI's /v1/audio/transcriptions API.
14///
15/// The audio file itself is carried out-of-band because the endpoint uses
16/// multipart/form-data, not JSON.
17#[serde_with::skip_serializing_none]
18#[derive(Debug, Clone, Default, Deserialize, Serialize, schemars::JsonSchema)]
19pub struct TranscriptionRequest {
20 /// ID of the model to use (e.g. "whisper-large-v3").
21 pub model: String,
22
23 /// Optional ISO-639-1 language hint for the input audio.
24 pub language: Option<String>,
25
26 /// Optional text prompt to guide the model's style / preserve continuity.
27 pub prompt: Option<String>,
28
29 /// Response format: `json` (default), `text`, `srt`, `verbose_json`, `vtt`.
30 pub response_format: Option<String>,
31
32 /// Sampling temperature (0..=1).
33 pub temperature: Option<f32>,
34
35 /// Timestamp granularities for verbose_json: `word`, `segment`.
36 pub timestamp_granularities: Option<Vec<String>>,
37
38 /// If true, stream partial transcription events as SSE.
39 pub stream: Option<bool>,
40}
41
42impl GenerationRequest for TranscriptionRequest {
43 fn is_stream(&self) -> bool {
44 self.stream.unwrap_or(false)
45 }
46
47 fn get_model(&self) -> Option<&str> {
48 Some(&self.model)
49 }
50
51 fn extract_text_for_routing(&self) -> String {
52 // Audio bytes are not visible here; use the optional prompt as a
53 // rough cache-aware routing hint when present.
54 self.prompt.clone().unwrap_or_default()
55 }
56}
57
58/// Binary audio payload for `/v1/audio/transcriptions`.
59///
60/// The transcription endpoint uses multipart/form-data, so the file bytes
61/// travel alongside the JSON-like `TranscriptionRequest` rather than inside it.
62#[derive(Debug, Clone)]
63pub struct AudioFile {
64 /// Raw audio bytes (wav/mp3/m4a/etc.).
65 pub bytes: bytes::Bytes,
66 /// Original filename from the multipart part. Forwarded verbatim to the worker.
67 pub file_name: String,
68 /// Original content-type of the audio part (e.g. `audio/wav`), if the client supplied one.
69 pub content_type: Option<String>,
70}