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;