(mut ctx: Context)
| 576 | #[cfg(feature = "master")] |
| 577 | #[cfg(feature = "luxtts")] |
| 578 | async fn run_master_luxtts(mut ctx: Context) -> Result<()> { |
| 579 | use cake_core::models::luxtts; |
| 580 | use cake_core::models::Generator; |
| 581 | |
| 582 | println!("[LuxTTS] Loading model from {}...", ctx.data_path.display()); |
| 583 | |
| 584 | let mut model = luxtts::LuxTTS::load(&mut ctx) |
| 585 | .await? |
| 586 | .ok_or_else(|| anyhow::anyhow!("failed to load LuxTTS model"))?; |
| 587 | |
| 588 | let prompt = ctx.args.prompt.clone(); |
| 589 | println!("[LuxTTS] Generating speech for: \"{}\"", prompt); |
| 590 | |
| 591 | // Load reference audio if provided |
| 592 | let reference_audio = if let Some(ref ref_path) = ctx.args.tts_reference_audio { |
| 593 | println!("[LuxTTS] Loading reference audio: {}", ref_path); |
| 594 | Some(load_wav_mono_24k(std::path::Path::new(ref_path))?) |
| 595 | } else { |
| 596 | None |
| 597 | }; |
| 598 | |
| 599 | let samples: Vec<f32> = model |
| 600 | .generate_speech( |
| 601 | &prompt, |
| 602 | reference_audio.as_deref(), |
| 603 | ctx.args.tts_t_shift, |
| 604 | ctx.args.tts_cfg_scale, |
| 605 | ctx.args.tts_diffusion_steps.min(10), // LuxTTS uses 4 steps by default |
| 606 | ctx.args.tts_speed, |
| 607 | ) |
| 608 | .await?; |
| 609 | |
| 610 | let output_path = std::path::Path::new(&ctx.args.audio_output); |
| 611 | luxtts::save_wav(&samples, output_path, 48000)?; |
| 612 | println!( |
| 613 | "[LuxTTS] Audio saved to {} ({:.1}s, {} samples @ 48kHz)", |
| 614 | output_path.display(), |
| 615 | samples.len() as f64 / 48000.0, |
| 616 | samples.len() |
| 617 | ); |
| 618 | Ok(()) |
| 619 | } |
| 620 | |
| 621 | #[cfg(feature = "master")] |
| 622 | async fn run_master_image(ctx: Context) -> Result<()> { |
no test coverage detected