Clean insight text for TTS and pass through Chatterbox tuning knobs

/tts/speech now normalizes input before synthesis: unwraps markdown
links/images to visible text, drops heading/list/blockquote/emphasis
markers and URLs, strips emoji (which non-turbo Chatterbox mispronounces
or skips), and collapses whitespace. Centralized in clean_for_tts so the
app, WebUI, and curl all get clean audio. Bracketed tags are deliberately
preserved for a future Turbo (paralinguistic) switch.

Adds optional exaggeration / cfg_weight / temperature to the request,
clamped to Chatterbox's documented ranges and forwarded on the speech
body. Unit tests cover markdown/emoji/URL stripping and tag preservation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 4.8 committed 2026-06-02 22:15:05 -04:00
1 parent 69268d03fe
commit 51be5df214
2 files changed
+118 -2

No files matched your search

+16
View File
@@ -138,11 +138,18 @@ impl LlamaCppClient {
/// Synthesize speech for `input` in an optional named `voice`, returning
/// the raw audio bytes (format per `response_format`, e.g. `"mp3"`/`"wav"`).
///
/// Chatterbox generation knobs are forwarded when set (caller is expected
/// to have range-clamped them): `exaggeration` (0.25–2.0, emotion),
/// `cfg_weight` (0.0–1.0, pace), `temperature` (0.05–5.0, randomness).
pub async fn text_to_speech(
&self,
input: &str,
voice: Option<&str>,
response_format: &str,
exaggeration: Option<f32>,
cfg_weight: Option<f32>,
temperature: Option<f32>,
) -> Result<Vec<u8>> {
let url = format!("{}/audio/speech", self.base_url);
let mut body = json!({
@@ -153,6 +160,15 @@ impl LlamaCppClient {
if let Some(v) = voice {
body["voice"] = Value::String(v.to_string());
}
if let Some(x) = exaggeration {
body["exaggeration"] = json!(x);
}
if let Some(x) = cfg_weight {
body["cfg_weight"] = json!(x);
}
if let Some(x) = temperature {
body["temperature"] = json!(x);
}
let resp = self
.client