use crate::cli::SoundEffectsArgs;
use crate::output::{print_info, print_success};
use crate::utils::{confirm_overwrite, generate_output_filename, write_bytes_to_file};
use anyhow::Result;
use colored::*;
use elevenlabs_rs::{
endpoints::genai::sound_effects::{CreateSoundEffect, CreateSoundEffectBody},
ElevenLabsClient,
};
use std::path::Path;
pub async fn execute(args: SoundEffectsArgs, api_key: &str, assume_yes: bool) -> Result<()> {
if args.text.is_empty() {
return Err(anyhow::anyhow!("Text description cannot be empty"));
}
if let Some(duration) = args.duration {
if !(0.5..=22.0).contains(&duration) {
return Err(anyhow::anyhow!(
"Duration must be between 0.5 and 22 seconds"
));
}
}
if let Some(influence) = args.influence {
if !(0.0..=1.0).contains(&influence) {
return Err(anyhow::anyhow!("Influence must be between 0 and 1"));
}
}
print_info("Generating sound effect...");
print_info(&format!("Prompt: {}", args.text.cyan()));
if let Some(duration) = args.duration {
print_info(&format!("Duration: {}s", duration));
} else {
print_info("Duration: auto");
}
let client = ElevenLabsClient::new(api_key);
let mut body = CreateSoundEffectBody::new(&args.text);
if let Some(duration) = args.duration {
body = body.with_duration_seconds(duration);
}
if let Some(influence) = args.influence {
body = body.with_prompt_influence(influence);
}
let endpoint = CreateSoundEffect::new(body);
let start_time = std::time::Instant::now();
let audio = client.hit(endpoint).await.map_err(|e| anyhow::anyhow!(e))?;
let duration = start_time.elapsed();
let output_path = if let Some(output) = args.output {
output
} else {
generate_output_filename("sound_effect", "mp3")
};
let path = Path::new(&output_path);
if !confirm_overwrite(path, assume_yes)? {
print_info("Cancelled");
return Ok(());
}
write_bytes_to_file(&audio, path)?;
print_success(&format!(
"Sound effect generated in {:.2}s -> {}",
duration.as_secs_f64(),
output_path.green()
));
Ok(())
}