chatterbox-tts-cli/README.md
dschlueter 34a34907a8 Bugfixes, Verbesserungen und Mixed-Language-Support
Bugfixes:
- Abkürzungen (z.B., d.h., Dr., Prof.) werden nicht mehr als Satzenden erkannt (_ABBREV_MASK_RE)
- Multilingual-Import: except Exception → except (ImportError, ModuleNotFoundError)
- tts_agent: ReAct-Schleife auf max. 10 Iterationen begrenzt, model_dump → explizites Dict
- tts_service: audio_device=None fällt auf 'pulse' zurück
- JSON-Fehlerbehandlung für --pronunciation-dict mit aussagekräftiger Meldung
- PlaybackWorker: Audio-Device wird vor Stream-Start via sd.query_devices() geprüft
- mcp_adapter: Fehlerbehandlung für HTTP-Fehler, Timeout erhöht, session_id ergänzt
- tts_agent: Health-Check beim Start, --speed/--first-chunk-len Validierung

Neue Features:
- Gemischtsprachige Texte: [en]...[/en]-Markierungen für per-Segment language_id
- strip_markdown(): entfernt Markdown-Formatierung vor der Synthese (--no-strip-markdown)
- Emoji-Entfernung in clean_raw_text() via unicodedata
- Pause/Resume: request_pause()/request_resume(), POST /pause, POST /resume, MCP-Tools
- Neue Einheiten: °C, °F, kWh, kW, W, V, A, J, kPa, bar, m², m³, m/s, rpm
- number_to_words_de/en bis Milliarden
- DEFAULT_PRONUNCIATION_DE erweitert (GitHub, YouTube, LinkedIn, Wi-Fi, iPhone, ChatGPT, …)
- NON_SPELLED_ACRONYMS erweitert (USB, CPU, GPU, API, CEO, HTML, …)
- Nummerierte Listen als separate Chunks behandelt
- Modell-Warmup via TTS_PRELOAD_LANG Env-Variable
- requirements.txt: Upper-Bounds für fastapi und uvicorn

Dokumentation: CLAUDE.md, README.md, BEDIENUNGSANLEITUNG.md vollständig aktualisiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 11:36:54 +02:00

412 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# chatterbox-tts-cli
Ein lokaler Text-to-Speech-Assistent auf Basis von
[Chatterbox TTS](https://github.com/resemble-ai/chatterbox) (Resemble AI).
Optimiert für deutsche Sprache; nutzbar als Kommandozeilen-Tool, als lokaler
HTTP-Service und als MCP-Server für KI-Assistenten.
## Features
- **Satz-für-Satz-Ausgabe** — gibt den ersten Satz aus, während die nächsten bereits generiert werden; minimale Latenz
- **Lückenlose Audiowiedergabe** — Callback-basierter OutputStream; keine Unterbrechungen zwischen Sätzen
- **Pause/Resume** — Ausgabe pausieren und fortsetzen ohne Datenverlust (`POST /pause`, `POST /resume`)
- **Geschwindigkeitsanpassung** — pitch-erhaltende Zeitstreckung via pyrubberband (R3-Engine); `--speed 0.5``2.0`
- **Voice Cloning** — optionale WAV-Referenz für Akzent und Klang
- **Mehrsprachig** — Deutsch, Englisch und 20+ weitere Sprachen via `ChatterboxMultilingualTTS`
- **Gemischtsprachige Texte** — `[en]...[/en]`-Markierungen für englische Passagen in deutschen Texten
- **Deutsche Textnormalisierung** — Abkürzungen (ARD → „Ah Er De"), Uhrzeiten (14:58 → „vierzehn Uhr achtundfünfzig"), Jahreszahlen bis Milliarden, Einheiten (°C, °F, kWh, m², …), Aussprache-Wörterbuch
- **Markdown-Bereinigung** — entfernt `**fett**`, `# Überschrift`, Links, Code-Blöcke automatisch vor der Synthese
- **HTTP-Service** — FastAPI-Service mit Job-Queue, Stop/Pause/Interrupt, Status-Endpunkt
- **MCP-Adapter** — direkte Integration in Claude Code, Claude Desktop und andere MCP-Hosts
- **Systemd-Autostart** — Service startet automatisch beim Login
---
## Systemvoraussetzungen
- Python 3.11+
- CUDA-GPU empfohlen (RTX 3070 oder besser; CPU möglich, aber langsam)
- Linux mit PipeWire oder PulseAudio
- `rubberband-cli` für Geschwindigkeitsanpassung:
```bash
sudo apt install rubberband-cli
```
---
## Installation
```bash
# 1. Conda-Umgebung
conda create -n chatterbox python=3.11
conda activate chatterbox
# 2. PyTorch mit CUDA (Beispiel CUDA 12.4)
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu124
# 3. Alle Abhängigkeiten
pip install -r requirements.txt
```
Beim ersten Start mit `--lang de` werden Modelle automatisch heruntergeladen (~23 GB, `~/.cache/huggingface/`).
---
## Kommandozeilen-CLI
```bash
conda activate chatterbox
# Deutschen Text vorlesen
python chatterbox_cli_v4.py --lang de --input text.txt
# Mit Voice Cloning
python chatterbox_cli_v4.py --lang de --voice stimme.wav --input text.txt
# Text direkt übergeben
python chatterbox_cli_v4.py --lang en --text "Hello, how are you?"
# Langsamer sprechen (pitch bleibt gleich)
python chatterbox_cli_v4.py --lang de --speed 0.85 --input text.txt
# Nur speichern, nicht abspielen
python chatterbox_cli_v4.py --lang de --no-play --output ausgabe.wav --input text.txt
# Aussprache-Wörterbuch
python chatterbox_cli_v4.py --lang de --pronunciation-dict aussprache.json --input text.txt
# Gemischtsprachiger Text
python chatterbox_cli_v4.py --lang de --text \
"Das [en]Machine Learning[/en] Modell kostet ca. 50 €."
# Markdown-Bereinigung deaktivieren
python chatterbox_cli_v4.py --lang de --no-strip-markdown --input text.txt
```
### CLI-Optionen
| Option | Standard | Beschreibung |
|--------|----------|--------------|
| `--text TEXT` | — | Text direkt als Argument |
| `--input DATEI` | — | UTF-8-Textdatei |
| `--lang CODE` | `de` | Sprachcode (de, en, fr, es, …) |
| `--voice DATEI.wav` | — | Referenz-WAV für Voice Cloning (1030 s) |
| `--speed N` | `1.0` | Wiedergabegeschwindigkeit (0.52.0) |
| `--audio-device` | `pulse` | Ausgabegerät (z. B. `pulse`, `default`) |
| `--t3-model` | `v3` | Multilingual-Modell: `v3` oder `v2` |
| `--acronym-mode` | `german` | Akronym-Modus: `german`, `space`, `period_space` |
| `--pronunciation-dict` | — | JSON-Datei mit Aussprache-Substitutionen |
| `--no-strip-markdown` | — | Markdown-Formatierung nicht entfernen |
| `--save` | nein | WAV-Datei speichern |
| `--output DATEI.wav` | — | Ausgabepfad (impliziert `--save`) |
| `--no-play` | — | Nicht live abspielen |
| `--no-sentence-mode` | — | Größere Chunks statt satzweise |
| `--stream` | — | Streaming-Modus (experimentell) |
| `--no-progress` | — | Weniger Konsolenausgabe |
| `--debug-delay N` | `0` | Pause vor jedem Satz (zum Testen) |
| `--stop` | — | Laufende Ausgabe abbrechen |
---
## Gemischtsprachige Texte
Deutsche Texte enthalten oft englische Fachbegriffe, Markennamen oder Zitate.
Mit `[xx]...[/xx]`-Markierungen werden diese Passagen mit der richtigen `language_id`
an das Multilingual-Modell übergeben:
```
Das [en]Machine Learning[/en] Framework kostet ca. 50 €.
Der [en]CEO[/en] sagte: [en]"We are committed to innovation."[/en]
```
Ohne Markierungen verhält sich das System identisch wie bisher.
Häufige englische Tech-Begriffe werden bereits automatisch korrekt ausgesprochen
(eingebaut in `DEFAULT_PRONUNCIATION_DE`):
| Begriff | Aussprache |
|---------|-----------|
| GitHub | „Git Hab" |
| YouTube | „Jutjub" |
| LinkedIn | „Linked In" |
| Wi-Fi | „Wai Fai" |
| iPhone | „Aiphone" |
| ChatGPT | „Tschet Dschie Pie Tie" |
---
## HTTP-Service (`tts_service.py`)
FastAPI-Service mit Job-Queue und Worker-Thread. Startet automatisch via systemd.
```bash
# Manueller Start
uvicorn tts_service:app --host 0.0.0.0 --port 9999
# Mit Modell-Warmup (kein Cold-Start beim ersten Request)
TTS_PRELOAD_LANG=de uvicorn tts_service:app --host 0.0.0.0 --port 9999
# Systemd (Autostart, läuft bereits)
systemctl --user status chatterbox-tts
systemctl --user restart chatterbox-tts
journalctl --user -u chatterbox-tts -f
```
### Endpunkte
| Methode | Pfad | Funktion |
|---------|------|----------|
| `POST` | `/speak` | Text in Queue einreihen |
| `POST` | `/stop` | Ausgabe abbrechen, Queue leeren |
| `POST` | `/pause` | Ausgabe pausieren (ohne Datenverlust) |
| `POST` | `/resume` | Pausierte Ausgabe fortsetzen |
| `GET` | `/health` | Service-Status und Gerät |
| `GET` | `/status` | Aktueller Job, Queue-Länge, letzte Jobs |
| `GET` | `/voices` | Unterstützte Sprachen |
### `/speak` Request-Body
```json
{
"text": "Hallo Welt",
"lang": "de",
"voice": null,
"interrupt": false,
"speed": 1.0,
"t3_model": "v3",
"audio_device": null,
"max_len": 400,
"save_wav": false,
"output_path": null,
"pronunciation_dict": null,
"session_id": null
}
```
```bash
# Beispiel
curl -X POST http://localhost:9999/speak \
-H "Content-Type: application/json" \
-d '{"text": "Hallo Welt", "lang": "de"}'
# Aus dem LAN
curl -X POST http://192.168.x.x:9999/speak \
-H "Content-Type: application/json" \
-d '{"text": "Text aus dem Netzwerk", "lang": "de"}'
# Laufende Ausgabe unterbrechen
curl -X POST http://localhost:9999/speak \
-H "Content-Type: application/json" \
-d '{"text": "Wichtiger Text", "lang": "de", "interrupt": true}'
# Pausieren und fortsetzen
curl -X POST http://localhost:9999/pause
curl -X POST http://localhost:9999/resume
# Stoppen
curl -X POST http://localhost:9999/stop
```
---
## MCP-Adapter (`mcp_adapter.py`)
Dünner Wrapper über die REST-API für MCP-fähige Hosts.
```bash
# stdio-Modus (Claude Code / Claude Desktop)
python mcp_adapter.py --stdio
# HTTP-Modus (andere MCP-Clients, Port 8001)
python mcp_adapter.py
# Anderen TTS-Service ansprechen
TTS_URL=http://192.168.1.10:9999 python mcp_adapter.py --stdio
```
### MCP-Tools
| Tool | Parameter | Funktion |
|------|-----------|----------|
| `speak` | text, lang, voice, interrupt, speed, session_id | Text ausgeben |
| `stop` | — | Ausgabe stoppen und Queue leeren |
| `pause` | — | Ausgabe pausieren (ohne Datenverlust) |
| `resume` | — | Pausierte Ausgabe fortsetzen |
| `get_status` | — | Aktuellen Job und Queue abfragen |
| `list_voices` | — | Unterstützte Sprachen auflisten |
### Claude Code Konfiguration
Bereits eingerichtet via `claude mcp add --scope user`. Zur manuellen Einrichtung:
```bash
claude mcp add --scope user chatterbox-tts \
/home/dschlueter/miniforge3/envs/chatterbox/bin/python \
/home/dschlueter/chatterbox-tts-cli/mcp_adapter.py --stdio
```
### Claude Desktop (`~/.config/claude/claude_desktop_config.json`)
```json
{
"mcpServers": {
"chatterbox-tts": {
"command": "/home/dschlueter/miniforge3/envs/chatterbox/bin/python",
"args": ["/home/dschlueter/chatterbox-tts-cli/mcp_adapter.py", "--stdio"]
}
}
}
```
---
## Integration mit KI-Tools
### Claude Code / Claude Desktop — MCP (fertig eingerichtet)
Claude kann direkt die Tools `speak`, `stop`, `pause`, `resume`, `get_status` und `list_voices` aufrufen.
Kein weiterer Setup nötig.
### Ollama (llama3.2, qwen2.5, mistral-nemo u. a.)
Modelle mit Tool-Support können den REST-Service über Function Calling ansprechen:
```python
import ollama, httpx
tools = [{
"type": "function",
"function": {
"name": "speak",
"description": "Text als Sprache ausgeben",
"parameters": {
"type": "object",
"properties": {
"text": {"type": "string"},
"lang": {"type": "string", "default": "de"},
"speed": {"type": "number", "default": 1.0},
},
"required": ["text"],
},
},
}]
resp = ollama.chat(model="qwen2.5", messages=[{"role": "user", "content": "..."}], tools=tools)
for call in resp.message.tool_calls or []:
if call.function.name == "speak":
httpx.post("http://127.0.0.1:9999/speak", json=call.function.arguments)
```
### TTS Agent (`tts_agent.py`)
Eigenständiger Konversationsagent mit eingebautem Function Calling:
```bash
# Mit Ollama
python tts_agent.py --model qwen2.5
# Mit LM Studio
python tts_agent.py --base-url http://localhost:1234/v1 --model local-model
# Mit OpenAI
OPENAI_API_KEY=sk-... python tts_agent.py --model gpt-4o
# Mit Voice Cloning
python tts_agent.py --model qwen2.5 --voice my_voice.wav
```
### Open WebUI
Im Open-WebUI-Menü unter *Tools* eine neue Python-Klasse anlegen:
```python
import requests
class Tools:
def speak(self, text: str, lang: str = "de") -> str:
"""Text als Sprache ausgeben."""
r = requests.post("http://127.0.0.1:9999/speak",
json={"text": text, "lang": lang}, timeout=10)
return r.json().get("job_id", "error")
def stop(self) -> str:
"""Laufende Sprachausgabe stoppen."""
requests.post("http://127.0.0.1:9999/stop", timeout=5)
return "stopped"
```
### Home Assistant
```yaml
# configuration.yaml
rest_command:
tts_speak:
url: "http://192.168.x.x:9999/speak"
method: POST
content_type: "application/json"
payload: '{"text": "{{ text }}", "lang": "de"}'
tts_stop:
url: "http://192.168.x.x:9999/stop"
method: POST
tts_pause:
url: "http://192.168.x.x:9999/pause"
method: POST
tts_resume:
url: "http://192.168.x.x:9999/resume"
method: POST
```
Aufruf in einer Automation:
```yaml
service: rest_command.tts_speak
data:
text: "Die Waschmaschine ist fertig."
```
### Node-RED / n8n
HTTP-Request-Node direkt auf `POST http://<host>:9999/speak` mit JSON-Body.
Kein weiterer Setup nötig.
---
## Aussprache-Wörterbuch
Für Namen oder Begriffe, die das Modell falsch ausspricht:
```json
{
"Xi Jinping": "Schi Dschinping",
"Putin": "Pjutin",
"Seoul": "Söul",
"Kubernetes": "Kubernetis"
}
```
```bash
python chatterbox_cli_v4.py --lang de \
--pronunciation-dict aussprache.json \
--input nachricht.txt
```
Häufige Begriffe sind bereits eingebaut (GitHub, YouTube, iPhone, Xi Jinping u. a.).
Das eigene Dict wird immer **nach** dem eingebauten angewendet — Überschreibungen sind möglich.
---
## Bekannte Einschränkungen
- **Wortbetonung** lässt sich nicht steuern — kein SSML. Abhilfe: Voice-Referenz mit gewünschter Betonung.
- **Laufendes `model.generate()`** kann nicht mid-call abgebrochen werden (Python-Thread-Grenzen); Stop/Pause greift am nächsten Chunk-Beginn.
- **Sprachmarkierungen `[en]...[/en]`** funktionieren nur mit `ChatterboxMultilingualTTS`; bei `--lang en` (mono) werden sie ignoriert.
- **Streaming-Modus** unterstützt keine Sprachmarkierungen.
---
## Lizenz
MIT — dieses Skript. Das Chatterbox-Modell: MIT-Lizenz (Resemble AI). Modellgewichte: CC BY-NC 4.0.