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}