# Bedienungsanleitung SpeechToText Diese Anleitung richtet sich an **Anwender**: Installieren, Starten, Benutzen, Einrichten mit Home Assistant, Probleme lösen. Für Programmierer: [docs/API.md](docs/API.md) (Schnittstellen) und [docs/ENTWICKLER.md](docs/ENTWICKLER.md) (Aufbau des Codes). ## Inhalt 1. [Was macht das Programm?](#1-was-macht-das-programm) 2. [Voraussetzungen](#2-voraussetzungen) 3. [Installation](#3-installation) 4. [Dienst starten und prüfen](#4-dienst-starten-und-prüfen) 5. [Benutzung mit der Kommandozeile (CLI)](#5-benutzung-mit-der-kommandozeile-cli) 6. [Das richtige Mikrofon](#6-das-richtige-mikrofon) 7. [Home Assistant anbinden](#7-home-assistant-anbinden) 8. [Andere Geräte im Netzwerk](#8-andere-geräte-im-netzwerk) 9. [Einstellungen](#9-einstellungen) 10. [Welches Whisper-Modell?](#10-welches-whisper-modell) 11. [Tipps für gute Erkennung](#11-tipps-für-gute-erkennung) 12. [Fehlerbehebung](#12-fehlerbehebung) 13. [Datenschutz](#13-datenschutz) 14. [Deinstallation](#14-deinstallation) --- ## 1. Was macht das Programm? SpeechToText wandelt **gesprochene Sprache in Text** um — vollständig **lokal** auf dem eigenen Rechner, ohne Cloud. Grundlage ist das Spracherkennungsmodell *Whisper* in der schnellen Umsetzung *faster-whisper*. Es besteht aus zwei Teilen: - **Dem Dienst** (`stt_service.py`): läuft im Hintergrund, hält das Sprachmodell im Speicher und nimmt Aufträge entgegen — von Home Assistant, von Mikrocontrollern, von Skripten oder von der CLI. - **Der Kommandozeile** (`stt_cli.py`): schickt Audiodateien oder das Mikrofon an den Dienst und gibt den erkannten Text aus. ```mermaid flowchart LR MIC[Mikrofon] --> CLI[stt_cli.py] FILE[Audiodatei] --> CLI HA[Home Assistant] -- Wyoming :10300 --> SVC ESP[ESP32 / Skripte / Apps] -- HTTP / WebSocket :9998 --> SVC CLI -- HTTP / WebSocket :9998 --> SVC[STT-Dienst
Whisper-Modell auf GPU] SVC --> TXT[Text] ``` **Wie schnell?** Auf einer RTX 3090 mit dem Modell `large-v3-turbo`: ein Satz von 6 Sekunden ist in 0,2 Sekunden erkannt, 35 Sekunden Sprache in 0,7 Sekunden. Beim freien Sprechen erscheint der Text etwa eine Sekunde, nachdem man aufgehört hat zu sprechen. **Wie merkt das Programm, dass ich fertig bin?** Es erkennt eine **Sprechpause** (Standard: 0,7 s Stille nach Sprache). Ein Stoppwort ist nicht nötig. --- ## 2. Voraussetzungen | | Minimum | Empfohlen | |---|---|---| | Betriebssystem | Linux (getestet: Ubuntu mit PipeWire) | | | Python | 3.11 | 3.12 (getestet) | | Grafikkarte | keine (läuft auch auf CPU, dann langsamer) | NVIDIA mit ≥ 4 GB freiem Speicher, CUDA 12 | | Arbeitsspeicher | 4 GB frei | 8 GB frei | | Festplatte | 0,5 GB (Modell `small`) | 2 GB (Modell `large-v3-turbo`) | | Mikrofon | beliebig (nur für Live-Betrieb) | ReSpeaker XVF3800 oder gutes USB-Mikrofon | Systemprogramme: `ffmpeg` ist hilfreich (Formatumwandlung), `pactl` (PipeWire/PulseAudio) für die Mikrofonwahl, `espeak-ng` nur für die automatischen Tests. --- ## 3. Installation ```bash cd ~/Python_Programs git clone SpeechToText # bzw. vorhandenen Ordner nutzen cd SpeechToText python3 -m venv --system-site-packages .venv .venv/bin/pip install -r requirements.txt ``` `--system-site-packages` nutzt bereits installierte Pakete (z. B. faster-whisper, CUDA-Bibliotheken) mit. Ohne vorhandene Installation lädt `pip` alles herunter. **Installation prüfen** (dauert ca. 10 Sekunden, braucht kein Modell): ```bash .venv/bin/python -m pytest # … 36 passed ``` > Beim **ersten Start des Dienstes** wird das Whisper-Modell aus dem Internet geladen > (`large-v3-turbo` ≈ 1,6 GB). Danach arbeitet alles offline. --- ## 4. Dienst starten und prüfen ### Manuell starten ```bash cd ~/Python_Programs/SpeechToText .venv/bin/python stt_service.py ``` Auf Rechnern mit **mehreren Grafikkarten** die gewünschte Karte fest angeben. Die Kennung (UUID) zeigt `nvidia-smi -L`: ```bash CUDA_VISIBLE_DEVICES=GPU-83ba6d1f-ebbe-f8c8-1433-153e0ebc3866 .venv/bin/python stt_service.py ``` > Warum UUID statt Nummer? `nvidia-smi` und CUDA nummerieren die Karten unterschiedlich. Mit der UUID > landet der Dienst sicher auf der richtigen Karte. Im Terminal erscheint u. a.: ``` INFO stt.service: Wyoming-Server auf tcp://0.0.0.0:10300 INFO stt: Lade Whisper-Modell large-v3-turbo (cuda, float16) INFO stt: Modell bereit nach 2.3s ``` Das Fenster offen lassen. **Beenden** mit `Strg+C`. ### Prüfen In einem zweiten Terminal: ```bash curl http://127.0.0.1:9998/health ``` `"status":"ok"` = bereit. `"status":"loading"` = Modell lädt noch (kurz warten). `"device":"cuda"` = läuft auf der Grafikkarte, `"cpu"` = auf dem Prozessor. Im Browser zeigt **http://127.0.0.1:9998/docs** alle Schnittstellen zum Ausprobieren. ### Optional: automatisch starten (systemd) Soll der Dienst dauerhaft laufen (nötig z. B. für Home Assistant nach einem Neustart): ```bash cp deploy/stt-service.service ~/.config/systemd/user/ # ggf. CUDA_VISIBLE_DEVICES und Einstellungen in der Datei anpassen systemctl --user daemon-reload systemctl --user enable --now stt-service ``` | Aufgabe | Befehl | |---|---| | Status | `systemctl --user status stt-service` | | Neustart (nach Änderungen) | `systemctl --user restart stt-service` | | Anhalten | `systemctl --user stop stt-service` | | Autostart abschalten | `systemctl --user disable --now stt-service` | | Live-Log | `journalctl --user -u stt-service -f` | Vorher einen manuell gestarteten Dienst beenden — beide wollen Port 9998. --- ## 5. Benutzung mit der Kommandozeile (CLI) Die CLI gibt **nur den erkannten Text** aus (Standardausgabe). Statusmeldungen stehen getrennt davon (Fehlerausgabe). Deshalb lässt sie sich direkt in Skripten verwenden. Alle Beispiele im Projektordner: `cd ~/Python_Programs/SpeechToText` ### Audiodateien ```bash .venv/bin/python stt_cli.py aufnahme.wav .venv/bin/python stt_cli.py interview.mp3 notiz.ogg # mehrere Dateien, eine Zeile je Datei .venv/bin/python stt_cli.py aufnahme.wav --json # mit Details .venv/bin/python stt_cli.py aufnahme.wav > text.txt # in Datei speichern ``` Unterstützt: WAV, MP3, OGG, FLAC, M4A, WebM und praktisch alle anderen Audioformate. ### Mikrofon ```bash .venv/bin/python stt_cli.py -v ``` Nach **„Bereit — sprich.“** einfach sprechen und kurz Pause machen. Jeder Satz erscheint als eigene Zeile. Beenden mit `Strg+C`. ``` Mikrofon: pulse → alsa_input.usb-Seeed_Studio_reSpeaker_XVF3800_… (16000 Hz, 2 Kanäle, Kanal 1) Bereit — sprich. (Strg+C beendet) … Sprache erkannt (2.3s) (3.1s Audio, 0.21s Rechenzeit) Schalte das Licht im Wohnzimmer ein. ``` ### Alle Optionen | Option | Bedeutung | |---|---| | `DATEI …` | Audiodateien transkribieren; ohne Datei wird das Mikrofon benutzt | | `-v`, `--verbose` | Statusdetails anzeigen (Sprachbeginn, Dauer, Rechenzeit) | | `--json` | Ergebnis als JSON-Zeile (Text, Sprache, Dauer, Rechenzeit …) | | `-l`, `--language` | Sprache: `de`, `en`, `fr` … oder `auto` (automatisch erkennen) | | `--prompt "…"` | Eigennamen/Fachbegriffe vorgeben, z. B. `--prompt "Bredelar, Marsberg"` | | `--once` | nach dem ersten erkannten Satz beenden | | `--timeout SEK` | Mikrofon nach SEK Sekunden beenden | | `--silence-ms MS` | Pausenlänge, die einen Satz beendet (Standard 700; für Denkpausen 1200–2000) | | `-d`, `--device` | Mikrofon wählen: Nummer oder Namensteil, z. B. `-d respeaker` | | `--channel N` | Mikrofonkanal wählen (ReSpeaker: automatisch 1) | | `--list-devices` | verfügbare Mikrofone anzeigen (`*` = Standard von PortAudio) | | `--url URL` | anderer Dienst, z. B. `--url http://192.168.1.10:9998` (auch per `STT_URL`) | | `--local` | **ohne Dienst**: Modell direkt laden (Start dauert länger) | | `--model NAME` | nur mit `--local`: Whisper-Modell, z. B. `small`, `large-v3-turbo` | | `--compute-device` | nur mit `--local`: `auto`, `cuda` oder `cpu` | | `--http-timeout SEK` | max. Wartezeit bei Dateien (Standard 300) | ### Rückgabewerte (für Skripte) | Code | Bedeutung | |---|---| | `0` | Text erkannt | | `1` | Fehler (Dienst nicht erreichbar, Datei fehlt …) | | `2` | keine Sprache erkannt (nur Stille/Geräusche, Zeitlimit abgelaufen) | | `130` | mit `Strg+C` abgebrochen, bevor ein Ergebnis vorlag (z. B. während einer Dateiübertragung) | ### Beispiele für Skripte ```bash # Einen Satz sprechen und in einer Variablen weiterverarbeiten text=$(.venv/bin/python stt_cli.py --once --timeout 15) [ $? -eq 0 ] && echo "Du hast gesagt: $text" # Alle MP3s eines Ordners in Textdateien umwandeln for f in aufnahmen/*.mp3; do .venv/bin/python stt_cli.py "$f" > "${f%.mp3}.txt" done # Diktat mit Denkpausen fortlaufend in eine Datei schreiben .venv/bin/python stt_cli.py --silence-ms 1500 >> notizen.txt ``` ### Ohne laufenden Dienst ```bash .venv/bin/python stt_cli.py --local --model large-v3-turbo aufnahme.wav .venv/bin/python stt_cli.py --local --model small --compute-device cpu -v # Mikrofon auf CPU ``` Praktisch für gelegentliche Nutzung; jeder Aufruf lädt das Modell aber neu (Sekunden bis Minuten). --- ## 6. Das richtige Mikrofon **Standard:** Ohne `-d` benutzt die CLI das Mikrofon, das in den **Systemeinstellungen** (Ubuntu: Einstellungen → Ton → Eingabe) ausgewählt ist. Die erste Statuszeile zeigt, welches: ``` Mikrofon: pulse → alsa_input.usb-Seeed_Studio_reSpeaker_XVF3800_… ``` **Anderes Mikrofon:** ```bash .venv/bin/python stt_cli.py --list-devices # Liste mit Nummern .venv/bin/python stt_cli.py -d 15 -v # per Nummer .venv/bin/python stt_cli.py -d respeaker -v # per Namensteil ``` **ReSpeaker XVF3800:** Das Gerät liefert zwei Kanäle. Der **rechte Kanal (1)** ist speziell für Spracherkennung aufbereitet (Echo- und Rauschunterdrückung). Die CLI erkennt den ReSpeaker am Namen und wählt Kanal 1 automatisch. Andere Mikrofone: beide Kanäle werden gemischt; mit `--channel 0`/`1` lässt sich ein Kanal erzwingen. **Pegel prüfen:** In den Toneinstellungen muss der Eingangspegel beim Sprechen ausschlagen. Wird nie „Sprache erkannt“ angezeigt, ist das Mikrofon meist falsch gewählt, stumm oder zu leise. --- ## 7. Home Assistant anbinden Der Dienst spricht das **Wyoming-Protokoll**, mit dem Home Assistant lokale Spracherkennung einbindet. 1. Dienst dauerhaft laufen lassen ([systemd](#optional-automatisch-starten-systemd)), sonst fehlt die Spracherkennung nach einem Neustart. 2. Port 10300 im Netzwerk erreichbar machen (siehe [Abschnitt 8](#8-andere-geräte-im-netzwerk)). 3. In Home Assistant: **Einstellungen → Geräte & Dienste → Integration hinzufügen → „Wyoming Protocol“** 4. **Host:** IP-Adresse des STT-Rechners, **Port:** `10300` → Absenden. Es erscheint „speech-to-text“. 5. **Einstellungen → Sprachassistenten** → Assistent öffnen → **Spracherkennung:** „speech-to-text“, Sprache „Deutsch“. 6. Testen, z. B. über das Mikrofon-Symbol in der Home-Assistant-App oder einen ESPHome-Satelliten (z. B. ESP32-S3-Box, M5Stack Atom Echo). Home Assistant bzw. der Satellit erkennt das Satzende selbst und schickt die komplette Aufnahme. Im Log des Dienstes erscheint pro Befehl eine Zeile `Wyoming-Transkript (…)`. --- ## 8. Andere Geräte im Netzwerk Der Dienst ist im ganzen Netzwerk erreichbar unter `http://:9998` (HTTP/WebSocket) und `:10300` (Wyoming). Die IP zeigt `hostname -I`. Ist eine Firewall aktiv, die Ports für das Heimnetz freigeben: ```bash sudo ufw allow from 192.168.1.0/24 to any port 9998 proto tcp comment 'SpeechToText HTTP' sudo ufw allow from 192.168.1.0/24 to any port 10300 proto tcp comment 'SpeechToText Wyoming' ``` (`192.168.1.0/24` an das eigene Netz anpassen.) > **Wichtig:** Der Dienst hat **kein Passwort**. Jeder im Netzwerk kann Audio schicken. Die Ports daher > **nicht ins Internet** freigeben (keine Portweiterleitung im Router). Wie Mikrocontroller (ESP32), Web-Apps oder eigene Programme den Dienst ansprechen, beschreibt [docs/API.md](docs/API.md) mit Beispielen. --- ## 9. Einstellungen Der Dienst wird über **Umgebungsvariablen** eingestellt: - **manuell:** vor den Startbefehl schreiben, z. B. `STT_MODEL=small STT_LANGUAGE=en .venv/bin/python stt_service.py` - **systemd:** in `~/.config/systemd/user/stt-service.service` als `Environment="STT_MODEL=small"`, danach `systemctl --user daemon-reload && systemctl --user restart stt-service` | Variable | Standard | Bedeutung | |---|---|---| | `STT_MODEL` | `large-v3-turbo` | Whisper-Modell, siehe [Abschnitt 10](#10-welches-whisper-modell) | | `STT_LANGUAGE` | `de` | Standardsprache; `auto` = automatisch erkennen | | `STT_DEVICE` | `auto` | `auto` (GPU wenn vorhanden), `cuda` oder `cpu` | | `STT_COMPUTE_TYPE` | `auto` | Rechengenauigkeit; `auto` = `float16` auf GPU, `int8` auf CPU | | `STT_CPU_MODEL` | `small` | Modell, falls die GPU nicht nutzbar ist und auf CPU ausgewichen wird | | `STT_CPU_THREADS` | `0` | CPU-Threads (0 = automatisch) | | `STT_BEAM_SIZE` | `5` | Suchbreite; `1` ist schneller, `5` genauer | | `STT_INITIAL_PROMPT` | – | Eigennamen/Fachbegriffe für alle Anfragen | | `STT_PRELOAD` | `1` | Modell sofort beim Start laden (`0` = erst bei der ersten Anfrage) | | `STT_MAX_QUEUE` | `8` | max. gleichzeitig wartende Aufträge, darüber Ablehnung („beschäftigt“) | | `STT_MAX_UPLOAD_MB` | `50` | größte erlaubte Audiodatei | | `STT_VAD_SILENCE_MS` | `700` | Pause, die beim Live-Streaming einen Satz beendet | | `STT_VAD_THRESHOLD` | `0.5` | Empfindlichkeit der Spracherkennung (höher = weniger Fehlauslösung durch Geräusche) | | `STT_VAD_MIN_SPEECH_MS` | `200` | Mindestlänge von Sprache (filtert Klicks und Klopfen) | | `STT_VAD_PRE_ROLL_MS` | `300` | Audio vor dem erkannten Sprachbeginn mitnehmen | | `STT_VAD_MAX_UTTERANCE_S` | `30` | längster Satz; längere Abschnitte werden geteilt | | `STT_WYOMING_PORT` | `10300` | Port für Home Assistant; leer = aus | | `STT_WYOMING_HOST` | `0.0.0.0` | Netzwerkschnittstelle für Wyoming | | `STT_HOST` / `STT_PORT` | `0.0.0.0` / `9998` | Adresse des HTTP-Dienstes (nur bei `python stt_service.py`) | | `STT_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` | | `STT_DOWNLOAD_ROOT` | – | eigener Ordner für Modelle (sonst Hugging-Face-Cache) | | `CUDA_VISIBLE_DEVICES` | – | Grafikkarte festlegen (UUID aus `nvidia-smi -L`) | --- ## 10. Welches Whisper-Modell? | Modell | Qualität Deutsch | Geschwindigkeit | Grafikspeicher | Einsatz | |---|---|---|---|---| | `tiny` | mäßig | sehr schnell | < 1 GB | nur Tests | | `base` | ausreichend für kurze Befehle | sehr schnell | ~1 GB | schwache Hardware | | `small` | gut | schnell, auch auf CPU brauchbar | ~1 GB | **CPU-Betrieb** | | `medium` | sehr gut | mittel | ~2–3 GB | | | `large-v3` | ausgezeichnet | langsamer | ~4 GB | höchste Genauigkeit bei langen Texten | | **`large-v3-turbo`** | ausgezeichnet | **schnell** | **~2,4 GB** | **Standard mit GPU** | Gemessen wurde in diesem Projekt nur `large-v3-turbo` (RTX 3090); `small` auf CPU ist durch die Tests erprobt. Die übrigen Angaben sind Richtwerte. Jedes Modell wird beim ersten Gebrauch einmalig heruntergeladen. --- ## 11. Tipps für gute Erkennung - **Abstand:** 30 cm bis 1 m zum Mikrofon, deutlich, aber normal sprechen. - **Pause am Satzende:** Nach dem Satz kurz innehalten — das signalisiert „fertig“. - **Denkpausen:** Wird ein Satz mitten drin abgeschnitten, `--silence-ms 1200` (oder mehr) verwenden. - **Eigennamen:** Werden Namen falsch geschrieben, mit `--prompt "Name1, Name2"` vorgeben. - **Hintergrundgeräusche:** Radio/Fernseher leiser; bei vielen Fehlauslösungen `STT_VAD_THRESHOLD=0.6`. - **Sprache fest einstellen:** `-l de` ist schneller und zuverlässiger als `auto`, besonders bei kurzen Sätzen. --- ## 12. Fehlerbehebung | Problem | Ursache | Lösung | |---|---|---| | `Fehler: … Connection refused` / „Läuft der Dienst?“ | Dienst nicht gestartet | Dienst starten ([Abschnitt 4](#4-dienst-starten-und-prüfen)) oder `--local` nutzen | | `/health` zeigt lange `loading` | erster Start: Modell wird heruntergeladen | Internetverbindung prüfen, warten; Fortschritt im Log | | `/health` zeigt `"device":"cpu"`, obwohl eine GPU da ist | GPU belegt/zu wenig Speicher/CUDA-Problem | Log lesen (`Laden auf cuda fehlgeschlagen: …`), `nvidia-smi` prüfen, andere Karte per `CUDA_VISIBLE_DEVICES` | | `/health` zeigt `error` | Modell nicht ladbar | Meldung im Feld `error`; Modellname und Speicherplatz prüfen | | Nie „Sprache erkannt“ | falsches/stummes Mikrofon | [Abschnitt 6](#6-das-richtige-mikrofon); Pegel in den Toneinstellungen prüfen | | Sätze werden mittendrin geteilt | Pausen zu lang für die Einstellung | `--silence-ms 1200` | | Text kommt erst sehr spät | Pausenerkennung sehr lang eingestellt oder CPU-Betrieb | `--silence-ms` verringern; GPU nutzen | | Wörter/Namen falsch | Aussprache, unbekannte Namen | `--prompt` mit Namen; größeres Modell; deutlicher sprechen | | „Untertitel im Auftrag des ZDF“ o. Ä. | Whisper-Halluzination bei Stille | wird normalerweise gefiltert; tritt es trotzdem auf, bitte Beispiel melden | | Wiederholte gleiche Sätze fehlen teilweise | Whisper fasst wörtliche Wiederholungen zusammen | bekannte Grenze; bei natürlicher Sprache selten | | `Warteschlange voll` / HTTP 503 | zu viele Aufträge gleichzeitig | kurz warten; `STT_MAX_QUEUE` erhöhen | | `Address already in use` beim Start | Port 9998/10300 belegt (zweiter Dienst läuft) | anderen Dienst beenden (`systemctl --user stop stt-service`) | | Home Assistant findet den Dienst nicht | Firewall, falsche IP, Dienst aus | `curl http://:9998/health` vom HA-Rechner; [Abschnitt 8](#8-andere-geräte-im-netzwerk) | | `Warnung: … Audioblöcke verworfen` | Netzwerk/Dienst zu langsam für das Mikrofon | Verbindung prüfen; lokal testen | **Log ansehen:** manuell gestartet → im Terminal; als systemd-Dienst → `journalctl --user -u stt-service -n 100`. Mehr Details mit `STT_LOG_LEVEL=DEBUG`. --- ## 13. Datenschutz - Die gesamte Spracherkennung läuft **lokal**. Audio und Text verlassen den Rechner nicht. - Internetzugriff nur beim **ersten Herunterladen** eines Modells (Hugging Face). - Der Dienst **speichert keine Aufnahmen** und keine Texte auf der Festplatte. - **Ausnahme Log:** Bei Home-Assistant-Anfragen (Wyoming) wird der erkannte Text im Log protokolliert (Stufe `INFO`). Wer das nicht möchte: `STT_LOG_LEVEL=WARNING`. - Der Dienst hat keine Zugangskontrolle → nur im eigenen Netz betreiben ([Abschnitt 8](#8-andere-geräte-im-netzwerk)). --- ## 14. Deinstallation ```bash systemctl --user disable --now stt-service 2>/dev/null rm -f ~/.config/systemd/user/stt-service.service && systemctl --user daemon-reload rm -rf ~/Python_Programs/SpeechToText ``` Heruntergeladene Modelle liegen im Hugging-Face-Cache (`$HF_HOME/hub` bzw. `~/.cache/huggingface/hub`, Ordner `models--*faster-whisper*`) und werden eventuell auch von anderen Programmen genutzt — nur löschen, wenn sicher ist, dass sie nicht mehr gebraucht werden.