Skip to main content

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}