openai_compat/resources/
audio.rs1use bytes::Bytes;
5use reqwest::Method;
6
7use crate::client::Client;
8use crate::error::OpenAIError;
9use crate::request::{MultipartField, RequestOptions};
10use crate::types::audio::{SpeechRequest, Transcription, TranscriptionRequest};
11use crate::types::files::FileUpload;
12
13#[derive(Debug, Clone)]
15pub struct Audio {
16 client: Client,
17}
18
19impl Audio {
20 pub(crate) fn new(client: Client) -> Self {
21 Self { client }
22 }
23
24 pub async fn speech(&self, request: SpeechRequest) -> Result<Bytes, OpenAIError> {
26 let body = serde_json::to_value(&request)?;
27 self.client
28 .execute_bytes(Method::POST, "/audio/speech", RequestOptions::json(body))
29 .await
30 }
31
32 pub async fn transcriptions(
38 &self,
39 file: FileUpload,
40 request: TranscriptionRequest,
41 ) -> Result<Transcription, OpenAIError> {
42 if matches!(
43 request.response_format.as_deref(),
44 Some("text") | Some("srt") | Some("vtt")
45 ) {
46 return Err(OpenAIError::Config(format!(
47 "response_format {:?} returns plain text; use transcriptions_raw",
48 request.response_format.as_deref().unwrap_or_default()
49 )));
50 }
51 let fields = transcription_fields(file, request);
52 self.client
53 .execute(
54 Method::POST,
55 "/audio/transcriptions",
56 RequestOptions::multipart(fields),
57 )
58 .await
59 }
60
61 pub async fn transcriptions_raw(
64 &self,
65 file: FileUpload,
66 request: TranscriptionRequest,
67 ) -> Result<String, OpenAIError> {
68 let fields = transcription_fields(file, request);
69 let bytes = self
70 .client
71 .execute_bytes(
72 Method::POST,
73 "/audio/transcriptions",
74 RequestOptions::multipart(fields),
75 )
76 .await?;
77 Ok(String::from_utf8_lossy(&bytes).into_owned())
78 }
79}
80
81fn transcription_fields(file: FileUpload, request: TranscriptionRequest) -> Vec<MultipartField> {
82 {
83 let mut fields = vec![
84 MultipartField::File {
85 name: "file".into(),
86 filename: file.filename,
87 bytes: file.bytes,
88 content_type: file.content_type,
89 },
90 MultipartField::Text {
91 name: "model".into(),
92 value: request.model,
93 },
94 ];
95 if let Some(language) = request.language {
96 fields.push(MultipartField::Text {
97 name: "language".into(),
98 value: language,
99 });
100 }
101 if let Some(prompt) = request.prompt {
102 fields.push(MultipartField::Text {
103 name: "prompt".into(),
104 value: prompt,
105 });
106 }
107 if let Some(response_format) = request.response_format {
108 fields.push(MultipartField::Text {
109 name: "response_format".into(),
110 value: response_format,
111 });
112 }
113 if let Some(temperature) = request.temperature {
114 fields.push(MultipartField::Text {
115 name: "temperature".into(),
116 value: temperature.to_string(),
117 });
118 }
119 fields
120 }
121}