From fdb6f3b1496c0ef35167de0fa5dd36a4a270ca4e Mon Sep 17 00:00:00 2001 From: Patrick szymkowiak Date: Wed, 18 Mar 2026 19:01:04 +0100 Subject: [PATCH] fix: revert kokoro to Python backend, restore say default on macOS Attempted pure Rust kokoro via kokoros crate but model only generates 0.5s audio regardless of text length (upstream bug). Reverted to Python subprocess which works correctly. Added hound dep for future Rust WAV writing. Restored say as default on macOS for reliability. --- Cargo.lock | 1 + Cargo.toml | 1 + src/backend/kokoro.rs | 23 +++++++++++++++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d1e805..02aecc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4070,6 +4070,7 @@ dependencies = [ "crossterm", "dirs", "futures-util", + "hound", "predicates", "qwen3-tts", "ratatui", diff --git a/Cargo.toml b/Cargo.toml index b3d0418..a3687e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" tempfile = "3" rodio = "0.20" +hound = "3" qwen3-tts = { git = "https://github.com/TrevorS/qwen3-tts-rs", features = ["hub"], default-features = false } ratatui = "0.29" crossterm = "0.28" diff --git a/src/backend/kokoro.rs b/src/backend/kokoro.rs index 22f10f0..a3f8e4b 100644 --- a/src/backend/kokoro.rs +++ b/src/backend/kokoro.rs @@ -1,13 +1,13 @@ -//! Kokoro TTS backend — pure Rust ONNX inference via Python kokoro-onnx bridge. +//! Kokoro TTS backend — ONNX model via Python kokoro-onnx bridge. //! -//! Cross-platform, no GPU required. Model files (~80MB) downloaded separately. +//! 82M param model, cross-platform. Model files (~80MB) downloaded separately. +//! Note: uses Python subprocess for now. Pure Rust port tracked as future work. use std::process::Command; use anyhow::{Context, Result}; use super::{SpeakOptions, TtsBackend}; -use crate::audio; use crate::config; const MODEL_FILE: &str = "kokoro-v1.0.onnx"; @@ -122,7 +122,22 @@ sf.write("{out}", samples, sr) anyhow::bail!("Kokoro TTS failed: {stderr}"); } - audio::play_wav_blocking(&wav_path)?; + // Use afplay on macOS (more reliable), rodio on other platforms + #[cfg(target_os = "macos")] + { + let status = Command::new("afplay") + .arg(&wav_path) + .status() + .context("failed to play audio")?; + if !status.success() { + anyhow::bail!("afplay failed"); + } + } + #[cfg(not(target_os = "macos"))] + { + crate::audio::play_wav_blocking(&wav_path)?; + } + let _ = std::fs::remove_file(&wav_path); Ok(()) }