fix(tts): sanitise text before SAPI so it stops reading "J.A.R.V.I.S." as "J точка A точка R точка..."
User complaint: SAPI reads every dotted acronym character-by-character with a "точка" between letters. Unbearable on every speak. No real TTS analog shipping yet (Silero/Coqui/Inworld in roadmap), so the immediate fix is text preprocessing. New module `jarvis-core::text_utils` with `sanitize_for_speech()`: - Specific brand mapping: J.A.R.V.I.S. → Джарвис, U.S.A. → США, U.K. → Британия, U.S. → США, S.O.S. → сос. - Generic dotted-acronym collapse: any `[letter].[letter].[letter].(...)` run of 3+ letters gets its dots stripped. "T.O.N." → "TON". - URL stripping: anything starting with http/https gets replaced with the word "ссылка". SAPI reading URLs char-by-char is unlistenable. - Em/en-dash normalisation: — → -, « » " stripped. - Whitespace collapse. Wired in two places: - `jarvis.speak(text, opts?)` Lua API runs sanitiser unless opts.raw=true. - `jarvis-app/llm_fallback::speak_via_sapi` runs sanitiser before the SAPI PowerShell shell-out for LLM auto-fallback replies. 5 unit tests in `text_utils::tests` covering jarvis-name collapse, generic acronym pattern, URL stripping, dash normalisation, and "leave clean russian sentences alone" — all green. Real TTS upgrade (Silero v4 first cut) tracked as P0.1 in roadmap.
This commit is contained in:
parent
9911b6ec40
commit
80b54af1ee
4 changed files with 164 additions and 5 deletions
|
|
@ -118,7 +118,8 @@ fn speak_via_sapi(text: &str) {
|
|||
if std::env::var("JARVIS_LLM_TTS").as_deref() == Ok("false") {
|
||||
return;
|
||||
}
|
||||
let escaped = text.replace('\'', "''");
|
||||
let cleaned = jarvis_core::text_utils::sanitize_for_speech(text);
|
||||
let escaped = cleaned.replace('\'', "''");
|
||||
let ps = format!(
|
||||
"Add-Type -AssemblyName System.Speech; \
|
||||
$s = New-Object System.Speech.Synthesis.SpeechSynthesizer; \
|
||||
|
|
@ -128,7 +129,7 @@ fn speak_via_sapi(text: &str) {
|
|||
}} \
|
||||
}} \
|
||||
$s.Speak('{}')",
|
||||
escaped
|
||||
escaped,
|
||||
);
|
||||
match std::process::Command::new("powershell")
|
||||
.args(["-NoProfile", "-Command", &ps])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue