(
ctx: Context,
model_path: &std::path::Path,
config_path: &std::path::Path,
)
| 363 | #[cfg(feature = "master")] |
| 364 | #[cfg(feature = "vibevoice")] |
| 365 | async fn run_vibevoice_0_5b( |
| 366 | ctx: Context, |
| 367 | model_path: &std::path::Path, |
| 368 | config_path: &std::path::Path, |
| 369 | ) -> Result<()> { |
| 370 | use cake_core::models::vibevoice; |
| 371 | |
| 372 | let weights_path = model_path.join("model.safetensors"); |
| 373 | println!("[VibeVoice-0.5B] Loading from {}", model_path.display()); |
| 374 | |
| 375 | let model = vibevoice::VibeVoiceTTS::load( |
| 376 | config_path, |
| 377 | &weights_path, |
| 378 | &ctx.device, |
| 379 | Some(ctx.args.tts_diffusion_steps), |
| 380 | &ctx.topology, |
| 381 | ctx.args.cluster_key.as_deref(), |
| 382 | ) |
| 383 | .await?; |
| 384 | |
| 385 | let prompt = &ctx.args.prompt; |
| 386 | println!("[VibeVoice-0.5B] Generating speech for: \"{}\"", prompt); |
| 387 | |
| 388 | let tokenizer = { |
| 389 | let local = model_path.join("tokenizer.json"); |
| 390 | if local.exists() { |
| 391 | tokenizers::Tokenizer::from_file(&local) |
| 392 | .map_err(|e| anyhow::anyhow!("tokenizer: {e}"))? |
| 393 | } else { |
| 394 | println!("[VibeVoice-0.5B] Downloading Qwen2.5 tokenizer..."); |
| 395 | let qwen_path = utils::hf::ensure_model_downloaded("Qwen/Qwen2.5-0.5B")?; |
| 396 | tokenizers::Tokenizer::from_file(qwen_path.join("tokenizer.json")) |
| 397 | .map_err(|e| anyhow::anyhow!("tokenizer: {e}"))? |
| 398 | } |
| 399 | }; |
| 400 | |
| 401 | let text_with_newline = format!("{}\n", prompt.trim()); |
| 402 | let encoding = tokenizer |
| 403 | .encode(text_with_newline.as_str(), false) |
| 404 | .map_err(|e| anyhow::anyhow!("tokenize: {e}"))?; |
| 405 | let token_ids = encoding.get_ids(); |
| 406 | println!("[VibeVoice-0.5B] Tokenized: {} tokens", token_ids.len()); |
| 407 | |
| 408 | let voice_path = ctx |
| 409 | .args |
| 410 | .voice_prompt |
| 411 | .as_ref() |
| 412 | .ok_or_else(|| anyhow::anyhow!("--voice-prompt required for TTS"))?; |
| 413 | let voice_prompt = vibevoice::VoicePrompt::load_f32( |
| 414 | std::path::Path::new(voice_path), |
| 415 | &ctx.device, |
| 416 | )?; |
| 417 | |
| 418 | let mut model = model; |
| 419 | let samples = model.generate( |
| 420 | token_ids, |
| 421 | &voice_prompt, |
| 422 | ctx.args.max_audio_frames, |
no test coverage detected