Skip to main content

openrouter/types/
audio_speech.rs

1//! Types for the text-to-speech endpoint (`POST /audio/speech`).
2//!
3//! Shapes mirror the Go SDK (`speech_models.go`). Named `audio_speech`
4//! rather than `audio` so it doesn't collide with the audio-input helpers
5//! in [`crate::types::multimodal`].
6
7use std::collections::BTreeMap;
8
9use bytes::Bytes;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12
13/// Audio output format requested from the TTS endpoint.
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(rename_all = "lowercase")]
16pub enum SpeechFormat {
17    /// MP3 audio bytes.
18    Mp3,
19    /// Raw PCM samples (defaults upstream when no format is requested).
20    Pcm,
21}
22
23impl SpeechFormat {
24    /// Lower-case wire value used in the request body.
25    pub fn as_str(self) -> &'static str {
26        match self {
27            SpeechFormat::Mp3 => "mp3",
28            SpeechFormat::Pcm => "pcm",
29        }
30    }
31}
32
33/// Request body for [`crate::Client::create_speech`].
34///
35/// `input`, `model`, and `voice` are required. `response_format` defaults
36/// to PCM upstream when left unset.
37#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
38pub struct SpeechRequest {
39    /// Text to synthesize.
40    pub input: String,
41    /// TTS model identifier.
42    pub model: String,
43    /// Provider-specific voice identifier (e.g. `alloy`, `nova`).
44    pub voice: String,
45    /// Output format. `None` defers to the provider default (PCM).
46    #[serde(skip_serializing_if = "Option::is_none", default)]
47    pub response_format: Option<SpeechFormat>,
48    /// Playback speed multiplier (only honored by providers that support
49    /// it, e.g. OpenAI TTS).
50    #[serde(skip_serializing_if = "Option::is_none", default)]
51    pub speed: Option<f64>,
52    /// Provider-specific passthrough configuration.
53    #[serde(skip_serializing_if = "Option::is_none", default)]
54    pub provider: Option<SpeechProvider>,
55}
56
57/// Provider-specific passthrough configuration for a TTS request.
58///
59/// `options` is keyed by provider slug; the map for the chosen provider
60/// is spread into the upstream request body.
61#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
62pub struct SpeechProvider {
63    /// Provider-keyed options. The map under the chosen provider's slug
64    /// is spread into the upstream request body.
65    #[serde(skip_serializing_if = "Option::is_none", default)]
66    pub options: Option<BTreeMap<String, BTreeMap<String, Value>>>,
67}
68
69/// Result of a TTS request: the raw audio bytes plus the upstream
70/// `Content-Type` and the resolved format (echoes the requested format,
71/// or PCM when none was requested).
72#[derive(Clone, Debug)]
73pub struct SpeechResponse {
74    /// Raw audio bytes returned by the provider.
75    pub audio: Bytes,
76    /// Upstream `Content-Type` header, when set.
77    pub content_type: Option<String>,
78    /// Resolved output format (echoes the requested format, or PCM).
79    pub format: SpeechFormat,
80}