Skip to content

Commit

Permalink
Add text-to-speech
Browse files Browse the repository at this point in the history
  • Loading branch information
Dongri Jin committed Dec 24, 2023
1 parent 1c31330 commit 1f56b88
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 2 deletions.
21 changes: 21 additions & 0 deletions examples/text_to_speech.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use openai_api_rs::v1::api::Client;
use openai_api_rs::v1::audio::{self, AudioSpeechRequest, TTS_1};
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string());

let req = AudioSpeechRequest::new(
TTS_1.to_string(),
String::from("Money is not problem, Problem is no money"),
audio::VOICE_ALLOY.to_string(),
String::from("problem.mp3"),
);

let result = client.audio_speech(req)?;
println!("{:?}", result);

Ok(())
}

// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example text_to_speech
40 changes: 38 additions & 2 deletions src/v1/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::v1::assistant::{
ListAssistant, ListAssistantFile,
};
use crate::v1::audio::{
AudioTranscriptionRequest, AudioTranscriptionResponse, AudioTranslationRequest,
AudioTranslationResponse,
AudioSpeechRequest, AudioSpeechResponse, AudioTranscriptionRequest, AudioTranscriptionResponse,
AudioTranslationRequest, AudioTranslationResponse,
};
use crate::v1::chat_completion::{ChatCompletionRequest, ChatCompletionResponse};
use crate::v1::completion::{CompletionRequest, CompletionResponse};
Expand Down Expand Up @@ -38,6 +38,9 @@ use crate::v1::run::{
use crate::v1::thread::{CreateThreadRequest, ModifyThreadRequest, ThreadObject};

use minreq::Response;
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::Path;

const API_URL_V1: &str = "https://api.openai.com/v1";

Expand Down Expand Up @@ -300,6 +303,39 @@ impl Client {
}
}

pub fn audio_speech(&self, req: AudioSpeechRequest) -> Result<AudioSpeechResponse, APIError> {
let res = self.post("/audio/speech", &req)?;
let bytes = res.as_bytes();
let path = req.output.as_str();
let path = Path::new(path);
if let Some(parent) = path.parent() {
match create_dir_all(parent) {
Ok(_) => {}
Err(e) => {
return Err(APIError {
message: e.to_string(),
})
}
}
}
match File::create(path) {
Ok(mut file) => match file.write_all(bytes) {
Ok(_) => {}
Err(e) => {
return Err(APIError {
message: e.to_string(),
})
}
},
Err(e) => {
return Err(APIError {
message: e.to_string(),
})
}
}
Ok(AudioSpeechResponse { result: true })
}

pub fn create_fine_tune(
&self,
req: CreateFineTuneRequest,
Expand Down
36 changes: 36 additions & 0 deletions src/v1/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,39 @@ impl_builder_methods!(
pub struct AudioTranslationResponse {
pub text: String,
}

pub const TTS_1: &str = "tts-1";
pub const TTS_1_HD: &str = "tts-1-hd";

pub const VOICE_ALLOY: &str = "alloy";
pub const VOICE_ECHO: &str = "echo";
pub const VOICE_FABLE: &str = "fable";
pub const VOICE_ONYX: &str = "onyx";
pub const VOICE_NOVA: &str = "nova";
pub const VOICE_SHIMMER: &str = "shimmer";

#[derive(Debug, Serialize, Clone)]
pub struct AudioSpeechRequest {
pub model: String,
pub input: String,
pub voice: String,
pub output: String,
}

impl AudioSpeechRequest {
pub fn new(model: String, input: String, voice: String, output: String) -> Self {
Self {
model,
input,
voice,
output,
}
}
}

impl_builder_methods!(AudioSpeechRequest,);

#[derive(Debug, Deserialize)]
pub struct AudioSpeechResponse {
pub result: bool,
}

0 comments on commit 1f56b88

Please sign in to comment.