Dokumentation: Bedienungsanleitung, API-Referenz, Entwicklerdoku, README überarbeitet
- BEDIENUNGSANLEITUNG.md: Installation, Betrieb, CLI, Mikrofon, Home Assistant, Einstellungen, Modellwahl, Fehlerbehebung, Datenschutz - docs/API.md: HTTP, WebSocket-Protokoll, Wyoming, Fehlercodes, geprüfte Beispiele - docs/ENTWICKLER.md: Architektur, Module, Nebenläufigkeit, Tests, Erweitern, Designentscheidungen - CLAUDE.md: Verweis auf die Dokumentation Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7a4d0e2885
commit
340100210d
1 changed files with 1430 additions and 89 deletions
155
README.md
155
README.md
|
|
@ -4,124 +4,87 @@ Lokaler, schneller Spracherkennungs-Dienst (Sprache → Text) auf Basis von
|
|||
[faster-whisper](https://github.com/SYSTRAN/faster-whisper) — das STT-Gegenstück zu
|
||||
[chatterbox-tts-cli](https://kitux.de/forgejo/dschlueter/chatterbox-tts-cli).
|
||||
|
||||
Gedacht als Baustein für Sprachassistenten und Smarthome: Home Assistant (Wyoming),
|
||||
Mikrocontroller wie ESP32 (HTTP/WebSocket), Skripte (CLI) und OpenAI-kompatible Tools.
|
||||
Gedacht als Baustein für Sprachassistenten und Smarthome: **Home Assistant** (Wyoming),
|
||||
**Mikrocontroller** wie ESP32 (HTTP/WebSocket), **Skripte** (CLI) und **OpenAI-kompatible Tools**.
|
||||
|
||||
- **Schnell:** Modell bleibt geladen. Gemessen auf RTX 3090 mit `large-v3-turbo`:
|
||||
5,8 s Audio → 0,2 s, 35 s Audio → 0,7 s Rechenzeit; ~2,4 GB VRAM.
|
||||
- **Nicht blockierend:** Inferenz in einem Worker-Thread, Warteschlange begrenzt (503 statt Stau).
|
||||
- **Äußerungsende per VAD** (Silero) statt Stoppwort; Transkript ca. 1 s nach Sprechende.
|
||||
- **Robust:** GPU-Fehler → automatischer CPU-Fallback; beliebige Audioformate; Halluzinationsfilter
|
||||
(„Untertitel im Auftrag des ZDF“ …).
|
||||
- **Nicht blockierend:** Inferenz in einem Worker-Thread, begrenzte Warteschlange (503 statt Stau).
|
||||
- **Äußerungsende per Sprechpause** (Silero-VAD) statt Stoppwort; Text ca. 1 s nach Sprechende.
|
||||
- **Robust:** automatischer CPU-Fallback, beliebige Audioformate, Filter gegen Whisper-Halluzinationen.
|
||||
- **Lokal:** keine Cloud; Internet nur zum einmaligen Herunterladen des Modells.
|
||||
|
||||
## Installation
|
||||
## Dokumentation
|
||||
|
||||
```bash
|
||||
python3 -m venv --system-site-packages .venv # nutzt vorhandenes faster-whisper/torch-Umfeld
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Dienst starten
|
||||
|
||||
```bash
|
||||
# Manuell (GPU per UUID pinnen: nvidia-smi -L)
|
||||
CUDA_VISIBLE_DEVICES=GPU-<uuid> .venv/bin/uvicorn stt_service:app --host 0.0.0.0 --port 9998
|
||||
|
||||
# Als systemd-User-Service (Autostart)
|
||||
cp deploy/stt-service.service ~/.config/systemd/user/
|
||||
systemctl --user daemon-reload && systemctl --user enable --now stt-service
|
||||
journalctl --user -u stt-service -f
|
||||
|
||||
curl http://127.0.0.1:9998/health
|
||||
```
|
||||
|
||||
Beim ersten Start wird das Modell heruntergeladen (`large-v3-turbo` ≈ 1,6 GB). Der Dienst ist sofort
|
||||
erreichbar; `/health` meldet `loading`, bis das Modell bereit ist.
|
||||
|
||||
### Konfiguration (Umgebungsvariablen)
|
||||
|
||||
| Variable | Standard | Bedeutung |
|
||||
| Dokument | Für wen | Inhalt |
|
||||
|---|---|---|
|
||||
| `STT_MODEL` | `large-v3-turbo` | Whisper-Modell (`tiny` … `large-v3`, `large-v3-turbo`, Pfad) |
|
||||
| `STT_DEVICE` | `auto` | `auto` / `cuda` / `cpu` |
|
||||
| `STT_COMPUTE_TYPE` | `auto` | `float16` (GPU) / `int8` (CPU) automatisch |
|
||||
| `STT_CPU_MODEL` | `small` | Modell beim Ausweichen auf CPU |
|
||||
| `STT_LANGUAGE` | `de` | Default-Sprache, `auto` = Erkennung |
|
||||
| `STT_BEAM_SIZE` | `5` | Beam-Search-Breite (1 = schneller) |
|
||||
| `STT_INITIAL_PROMPT` | – | Kontext/Eigennamen für Whisper |
|
||||
| `STT_MAX_QUEUE` | `8` | max. wartende Aufträge, darüber HTTP 503 |
|
||||
| `STT_MAX_UPLOAD_MB` | `50` | max. Uploadgröße |
|
||||
| `STT_PRELOAD` | `1` | Modell beim Start laden + aufwärmen |
|
||||
| `STT_VAD_SILENCE_MS` | `700` | Stille bis Äußerungsende (Streaming) |
|
||||
| `STT_VAD_THRESHOLD` | `0.5` | Silero-Sprachschwelle |
|
||||
| `STT_VAD_MAX_UTTERANCE_S` | `30` | max. Äußerungslänge |
|
||||
| `STT_WYOMING_HOST` / `STT_WYOMING_PORT` | `0.0.0.0` / `10300` | Wyoming-Server, Port leer = aus |
|
||||
| `STT_LOG_LEVEL` | `INFO` | Log-Level |
|
||||
| **[BEDIENUNGSANLEITUNG.md](BEDIENUNGSANLEITUNG.md)** | Anwender | Installation, Starten, CLI, Mikrofon, Home Assistant, Einstellungen, Fehlerbehebung |
|
||||
| **[docs/API.md](docs/API.md)** | Client-Entwickler | HTTP, WebSocket-Protokoll, Wyoming, Fehlercodes, Beispiele (Python, curl, ESP32) |
|
||||
| **[docs/ENTWICKLER.md](docs/ENTWICKLER.md)** | Programmierer am Projekt | Architektur, Module, Nebenläufigkeit, Tests, Erweitern, Designentscheidungen |
|
||||
|
||||
## Schnittstellen
|
||||
|
||||
### HTTP
|
||||
## Schnellstart
|
||||
|
||||
```bash
|
||||
# OpenAI-kompatibel (multipart) — response_format: json | text | verbose_json
|
||||
curl -F file=@aufnahme.mp3 -F language=de http://127.0.0.1:9998/v1/audio/transcriptions
|
||||
cd ~/Python_Programs/SpeechToText
|
||||
python3 -m venv --system-site-packages .venv
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
|
||||
# Rohdaten im Body — ideal für Mikrocontroller (kein multipart nötig)
|
||||
# Dienst starten (GPU per UUID aus `nvidia-smi -L`; ohne GPU einfach weglassen)
|
||||
CUDA_VISIBLE_DEVICES=GPU-<uuid> .venv/bin/python stt_service.py
|
||||
|
||||
# in einem zweiten Terminal
|
||||
curl http://127.0.0.1:9998/health # "status":"ok" = bereit
|
||||
.venv/bin/python stt_cli.py aufnahme.wav # Datei → Text
|
||||
.venv/bin/python stt_cli.py -v # Mikrofon → Text (Strg+C beendet)
|
||||
```
|
||||
|
||||
Beim ersten Start wird das Modell geladen (`large-v3-turbo` ≈ 1,6 GB). Schnittstellen zum Ausprobieren
|
||||
im Browser: http://127.0.0.1:9998/docs
|
||||
|
||||
## Schnittstellen auf einen Blick
|
||||
|
||||
| Schnittstelle | Adresse | Zweck |
|
||||
|---|---|---|
|
||||
| `GET /health` | `:9998` | Status, Modell, Gerät, Warteschlange |
|
||||
| `POST /v1/audio/transcriptions` | `:9998` | OpenAI-kompatibel (multipart) |
|
||||
| `POST /transcribe` | `:9998` | Audio direkt im Body (WAV/MP3/… oder rohes PCM) — ideal für Mikrocontroller |
|
||||
| `WS /ws/stream` | `:9998` | Live-Streaming mit automatischer Satzende-Erkennung |
|
||||
| Wyoming | `tcp :10300` | Home Assistant / ESPHome-Satelliten |
|
||||
|
||||
```bash
|
||||
curl --data-binary @aufnahme.wav http://127.0.0.1:9998/transcribe
|
||||
curl --data-binary @roh.pcm "http://127.0.0.1:9998/transcribe?format=pcm&sample_rate=16000&channels=1"
|
||||
curl -F file=@aufnahme.mp3 http://127.0.0.1:9998/v1/audio/transcriptions
|
||||
```
|
||||
|
||||
`/transcribe` liefert `text`, `language`, `duration`, `processing_s`, `segments`.
|
||||
> Der Dienst hat keine Authentifizierung — nur im eigenen Netz betreiben.
|
||||
|
||||
### WebSocket `/ws/stream` (Live-Streaming)
|
||||
## Projektaufbau
|
||||
|
||||
Client schickt s16le-PCM in beliebig großen Stücken; der Dienst erkennt Äußerungen selbst.
|
||||
|
||||
```text
|
||||
→ {"type":"start","sample_rate":16000,"channels":1,"channel":null,"language":"de","vad":true,"silence_ms":700}
|
||||
→ <binär: PCM> …
|
||||
← {"type":"speech_start","t":1.31}
|
||||
← {"type":"transcript","text":"Schalte das Licht ein.","language":"de","duration":2.4,"processing_s":0.21,"reason":"silence","t":3.9}
|
||||
→ {"type":"end"} # laufende Äußerung abschließen → danach {"type":"done"}
|
||||
→ {"type":"close"} # ausstehende Transkripte senden, dann schließen
|
||||
```
|
||||
|
||||
Ohne VAD (`"vad":false`) wird alles bis `end` gesammelt und als Ganzes transkribiert (Push-to-Talk).
|
||||
Für ESP32: I²S-Mikrofon mit 16 kHz mono lesen und die Puffer direkt als Binär-Frames senden.
|
||||
|
||||
### Home Assistant (Wyoming)
|
||||
|
||||
Einstellungen → Geräte & Dienste → Integration hinzufügen → **Wyoming Protocol** →
|
||||
Host = dieser Rechner, Port `10300`. Danach in der Sprachassistenten-Pipeline als
|
||||
Spracherkennung auswählen. ESPHome-Satelliten nutzen den Dienst dann automatisch.
|
||||
|
||||
## CLI
|
||||
|
||||
Nur Transkripte auf stdout, Status auf stderr → skriptfähig.
|
||||
|
||||
```bash
|
||||
.venv/bin/python stt_cli.py aufnahme.wav # Datei über den Dienst
|
||||
.venv/bin/python stt_cli.py *.mp3 --json # JSON-Zeilen
|
||||
.venv/bin/python stt_cli.py # Mikrofon (System-Default), fortlaufend
|
||||
text=$(.venv/bin/python stt_cli.py --once) # eine Äußerung → Variable
|
||||
.venv/bin/python stt_cli.py -d respeaker -v # bestimmtes Gerät (ReSpeaker: ASR-Kanal automatisch)
|
||||
.venv/bin/python stt_cli.py --local --model small aufnahme.wav # ohne Dienst
|
||||
.venv/bin/python stt_cli.py --list-devices
|
||||
```
|
||||
|
||||
Exit-Codes: `0` ok, `1` Fehler, `2` keine Sprache erkannt.
|
||||
| Datei | Aufgabe |
|
||||
|---|---|
|
||||
| `stt_core.py` | Kern: Whisper-Engine, Audio-Hilfen, Halluzinationsfilter, Satzende-Erkennung |
|
||||
| `stt_service.py` | FastAPI-Dienst: HTTP, WebSocket, Worker, Start des Wyoming-Servers |
|
||||
| `stt_wyoming.py` | Wyoming-Protokoll für Home Assistant |
|
||||
| `stt_cli.py` | Kommandozeile: Dateien und Mikrofon über den Dienst oder lokal |
|
||||
| `tests/` | Unit-Tests (ohne Modell) und Integrationstests (echtes Whisper) |
|
||||
| `deploy/stt-service.service` | systemd-User-Unit für den Dauerbetrieb |
|
||||
| `legacy/` | alte Einzelskripte `stt.py`, `stt_respeaker.py` (historisch, nicht gepflegt) |
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m pytest # schnell, ohne Modell (Fake-Engine)
|
||||
.venv/bin/python -m pytest -m integration # echtes Whisper (small, CPU) + Silero mit espeak-ng-Sprache
|
||||
.venv/bin/python -m pytest tests/test_core.py::test_segmenter_detects_two_utterances
|
||||
.venv/bin/python -m pytest # 36 Unit-Tests, ohne Modell
|
||||
.venv/bin/python -m pytest -m integration # 4 Integrationstests: Whisper small (CPU) + Silero, espeak-ng-Sprache
|
||||
```
|
||||
|
||||
## Bekannte Grenzen
|
||||
|
||||
- Wörtlich wiederholte Sätze innerhalb eines 30-s-Fensters fasst Whisper teils zusammen
|
||||
(bei natürlicher Sprache selten).
|
||||
- Keine wortweisen Zwischenergebnisse während des Sprechens — Transkript kommt pro Äußerung.
|
||||
- `legacy/stt.py` und `legacy/stt_respeaker.py` sind die alten Einzelskripte (historisch, nicht gepflegt).
|
||||
- Keine Zwischenergebnisse während des Sprechens — Text kommt pro Äußerung.
|
||||
- Keine Authentifizierung und kein TLS.
|
||||
|
||||
## Lizenz und Autor
|
||||
|
||||
Autor: dschlueter. Verwendete Komponenten: faster-whisper (MIT), OpenAI Whisper-Modelle (MIT),
|
||||
Silero VAD (MIT), Wyoming (MIT), FastAPI (MIT).
|
||||
|
|
|
|||
Loading…
Reference in a new issue