Read-aloud: natural neural voice via local Piper TTS
Replace the browser's robotic Web Speech API (espeak on Chromium) as the
primary read-aloud path with server-side Piper neural TTS, served by petal
and kept fully offline on millenia next to Ollama.
- internal/tts: proxy short passages to Piper, transcode WAV -> mp3/opus via
ffmpeg, content-addressed disk cache (instant re-taps). Each Piper instance
loads one voice, so language routes to its own endpoint:{voice}. Unknown
language -> 404 so the client falls back to Web Speech. UTF-8-safe truncation
for multibyte (Chinese) text.
- config: TTS_ENDPOINT / TTS_ENDPOINT_ZH / TTS_VOICE_EN / TTS_VOICE_ZH /
TTS_CACHE_DIR / TTS_TIMEOUT / TTS_AUDIO_FORMAT. Route mounts only when
TTS_ENDPOINT is set; otherwise unchanged behavior.
- web/audio/speech.ts: speak() hits /api/tts first, falls back to Web Speech on
any failure; rapid-tap-safe via a request token. Call sites unchanged.
- deploy/: Piper user systemd units (EN :5005, ZH :5006), setup script, README.
English (en_US-amy-medium) and Chinese (zh_CN-huayan-medium) are both live.
Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd
This commit is contained in:
14
.env.example
14
.env.example
@@ -17,6 +17,20 @@ LLM_MODEL= # checkpoint model (small/fast). Never hardcod
|
||||
LLM_CHAT_MODEL= # Ask Petal model (Mandarin-native). Falls back to LLM_MODEL if empty.
|
||||
LLM_TIMEOUT=30s
|
||||
|
||||
# Read-aloud (TTS). Off unless TTS_ENDPOINT is set — when empty, the /api/tts route
|
||||
# is not mounted and the frontend falls back to the browser's Web Speech API.
|
||||
# Backed by a local Piper HTTP server (python3 -m piper.http_server).
|
||||
# Each Piper HTTP server loads ONE voice, so English and Chinese need separate
|
||||
# instances (different ports). zh is only routed when both TTS_ENDPOINT_ZH and
|
||||
# TTS_VOICE_ZH are set; otherwise Chinese falls back to Web Speech.
|
||||
TTS_ENDPOINT= # e.g. http://127.0.0.1:5005 — empty disables server TTS
|
||||
TTS_ENDPOINT_ZH= # e.g. http://127.0.0.1:5006 — Chinese Piper instance
|
||||
TTS_VOICE_EN=en_US-amy-medium # Piper voice id for English
|
||||
TTS_VOICE_ZH=zh_CN-huayan-medium # Piper voice id for Chinese
|
||||
TTS_CACHE_DIR=./data/tts # on-disk store for synthesized clips (content-addressed)
|
||||
TTS_TIMEOUT=15s
|
||||
TTS_AUDIO_FORMAT=mp3 # mp3 | opus | wav — mp3/opus transcode Piper's WAV via ffmpeg
|
||||
|
||||
# --- Deferred (not wired in the local-dev build) ---
|
||||
|
||||
# Auth (Authentik OIDC) — deferred; single hardcoded local user for now
|
||||
|
||||
Reference in New Issue
Block a user