Skip to main content

rig_core/
audio_generation.rs

1//! Text-to-speech requests and normalized audio responses.
2//!
3//! ```no_run
4//! use rig_core::DynModel;
5//! use rig_core::audio_generation::AudioGenerationRequestBuilder;
6//! use rig_core::operation::AudioGeneration;
7//!
8//! # async fn example(model: DynModel<AudioGeneration>, voice: &str) -> Result<(), Box<dyn std::error::Error>> {
9//! let request = AudioGenerationRequestBuilder::new("Hello", voice).build();
10//! let response = model.call(request).await?;
11//! # let _ = response;
12//! # Ok(())
13//! # }
14//! ```
15use crate::completion::Usage;
16use serde::{Deserialize, Serialize};
17use serde_json::Value;
18
19/// Generated audio and normalized provider metadata.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct AudioGenerationResponse {
22    /// The generated audio bytes.
23    pub audio: Vec<u8>,
24    /// Usage as the provider reported it; every counter is `None` when the
25    /// provider reported none (see [`Usage`]).
26    #[serde(default)]
27    pub usage: Usage,
28    /// Stable descriptor name of the provider that produced this response,
29    /// for example `"openai"`. Always populated.
30    pub provider: String,
31    /// Provider-reported model identifier, when the wire response named one.
32    #[serde(default)]
33    pub model: Option<String>,
34    /// Provider-assigned response-scoped identifier, when reported.
35    #[serde(default, skip_serializing_if = "Option::is_none")]
36    pub response_id: Option<String>,
37    /// Transport request ID from HTTP headers, or `None` when unreported.
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub provider_request_id: Option<String>,
40    /// Provider response metadata. May be null for byte-only responses or
41    /// responses constructed without metadata; audio bytes remain in [`Self::audio`].
42    #[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
43    pub raw: serde_json::Value,
44}
45
46impl AudioGenerationResponse {
47    /// A response carrying `audio`. The driver writes the provider, the
48    /// transport request id and the reply document; decoders set what the
49    /// provider reported.
50    pub fn new(audio: Vec<u8>) -> Self {
51        Self {
52            audio,
53            usage: Usage::default(),
54            provider: String::new(),
55            model: None,
56            response_id: None,
57            provider_request_id: None,
58            raw: serde_json::Value::Null,
59        }
60    }
61}
62
63pub struct AudioGenerationRequest {
64    pub text: String,
65    pub voice: String,
66    pub speed: f32,
67    pub additional_params: Option<Value>,
68}
69
70/// Builds a speech request for a text and voice. The speed defaults to 1.0.
71pub struct AudioGenerationRequestBuilder {
72    request: AudioGenerationRequest,
73}
74
75impl AudioGenerationRequestBuilder {
76    /// A request to speak `text` in `voice`.
77    pub fn new(text: impl Into<String>, voice: impl Into<String>) -> Self {
78        Self {
79            request: AudioGenerationRequest {
80                text: text.into(),
81                voice: voice.into(),
82                speed: 1.0,
83                additional_params: None,
84            },
85        }
86    }
87
88    /// The speed of the generated audio.
89    pub fn speed(mut self, speed: f32) -> Self {
90        self.request.speed = speed;
91        self
92    }
93
94    /// Merges provider-specific parameters over earlier ones, key by key for
95    /// JSON objects; `None` clears existing parameters.
96    pub fn additional_params(mut self, params: impl Into<Option<Value>>) -> Self {
97        self.request.additional_params =
98            crate::json_utils::merge_params(self.request.additional_params.take(), params.into());
99        self
100    }
101
102    /// Builds the audio generation request.
103    pub fn build(self) -> AudioGenerationRequest {
104        self.request
105    }
106}
107
108#[cfg(test)]
109mod builder_tests;
110#[cfg(test)]
111mod provider_response_tests;