# Bedienungsanleitung — Voice Assistant ## Inhaltsverzeichnis 1. [Voraussetzungen](#1-voraussetzungen) 2. [Installation der Abhängigkeiten](#2-installation-der-abhängigkeiten) 3. [Schnellstart](#3-schnellstart) 4. [Die fünf Zustände](#4-die-fünf-zustände) 5. [Steuer-Wörter](#5-steuer-wörter) 6. [Alle Kommandozeilenoptionen](#6-alle-kommandozeilenoptionen) 7. [Mikrofon wählen](#7-mikrofon-wählen) 8. [Audio-Ausgang wählen](#8-audio-ausgang-wählen) 9. [LLM-Backend konfigurieren](#9-llm-backend-konfigurieren) 10. [Sprache und Stimme](#10-sprache-und-stimme) 11. [Standalone-Werkzeuge](#11-standalone-werkzeuge) 12. [Tipps und Fehlerbehebung](#12-tipps-und-fehlerbehebung) --- ## 1. Voraussetzungen ### Hardware | Komponente | Empfehlung | |---|---| | Mikrofon | ReSpeaker XVF3800 (Hardware-AEC, 4 Mikrofone, 48 kHz) | | GPU | NVIDIA RTX (CUDA) für Whisper-Transkription | | Audio-System | PipeWire mit `paplay` | Jedes USB-Mikrofon funktioniert. Das ReSpeaker XVF3800 ist empfohlen, weil es Hardware-seitig Echo cancellation (AEC) und Beamforming bietet — das verhindert, dass die TTS-Ausgabe als Spracheingabe erkannt wird. ### Software - Python 3.12+ - PipeWire als Audio-Server (`pactl`, `paplay` müssen verfügbar sein) - CUDA-Treiber für NVIDIA-GPU --- ## 2. Installation der Abhängigkeiten ```bash pip install faster-whisper openwakeword piper-tts sounddevice scipy langdetect openai ``` Das Whisper-Modell (`large-v3`) wird beim ersten Start automatisch heruntergeladen (~3 GB). Piper-Stimmen werden bei Bedarf automatisch heruntergeladen (~60–120 MB pro Sprache). --- ## 3. Schnellstart ```bash # Standard: ReSpeaker-Mikrofon, llama.cpp auf localhost:8001, Deutsch python3 assistant.py # Ohne Wake-Word — sofort aufnahmebereit (gut zum Testen) python3 assistant.py --no-wakeword # Mit Ollama python3 assistant.py --backend ollama --model llama3.2 # Mit OpenAI export OPENAI_API_KEY=sk-... python3 assistant.py --backend openai --model gpt-4o-mini ``` Beim ersten Start werden Modelle geladen (ca. 10–30 Sekunden). Danach erscheint: ``` Warte auf "Hey Jarvis" … [LAUSCH] Warte auf "Hey Jarvis" … ``` --- ## 4. Die fünf Zustände Der Assistent durchläuft folgende Zustände. Der aktuelle Zustand wird in der Statuszeile links in eckigen Klammern angezeigt: `[ZUSTAND] Info` ``` "Hey Jarvis" LAUSCH ─────────────► AUFNAHME ▲ │ │ Timeout/Stopp Stille ≥5s │ oder "over" │ │ │ Stopp ▼ DIALOG ◄──────────── VORLESE ◄── GENERATOR │ Vorlesen fertig Transkription │ + LLM-Antwort └── Sprache erkannt ──► AUFNAHME ``` ### LAUSCH Wartet auf das Wake-Word **„Hey Jarvis"**. Kein Quittungston, kein Feedback bis das Wake-Word erkannt wird. Ein kurzer Piepton signalisiert den Übergang zu AUFNAHME. ### AUFNAHME Nimmt die Sprache auf. Die Statuszeile zeigt die bisherige Aufnahmedauer und die aktuelle Stille-Dauer: ``` [AUFNAHME] 3.2s (Stille 1.1s) ``` Die Aufnahme endet wenn: - Stille ≥ `--silence-sec` (Standard: 5 Sekunden) - Das Stop-Wort gesagt wird (Standard: „over") - „Stopp" gesagt wird → direkt zurück zu LAUSCH (ohne Antwort) - Maximaldauer von 60 Sekunden erreicht ist ### GENERATOR Der Assistent sagt den Quittungssatz (Standard: „Moment, ich antworte gleich."), während er die Transkription und den LLM-Aufruf durchführt. Auch hier ist „Stopp" aktiv und bricht den Vorgang ab. ### VORLESE Die Antwort wird vorgelesen. Alle **Steuer-Wörter** sind aktiv (→ Abschnitt 5). Mehrere Sätze werden parallel synthetisiert und nahtlos abgespielt. ### DIALOG Nach dem Vorlesen öffnet sich ein Zeitfenster (Standard: 5 Sekunden). Wird in dieser Zeit gesprochen, geht der Assistent direkt in AUFNAHME — **ohne Wake-Word**. So sind Rückfragen flüssig möglich. Nach Ablauf des Zeitfensters oder bei „Stopp" kehrt der Assistent zu LAUSCH zurück. --- ## 5. Steuer-Wörter Das Wort **„bitte"** wird vor dem Abgleich immer ignoriert (z. B. „Stopp bitte" = „Stopp"). ### Während VORLESE | Gesprochener Befehl | Wirkung | |---|---| | **„Stopp"** | Wiedergabe sofort abbrechen → DIALOG | | **„Pause"** | Wiedergabe anhalten (bleibt pausiert) | | **„Weiter"** | Nach Pause: aktuellen Satz von vorne abspielen | | **„Noch einmal"** | Letzten Satz wiederholen | | **„Absatz noch einmal"** | Zum Anfang des letzten Absatzes springen | | **„Alles von vorn"** | Gesamte Antwort von Anfang an wiederholen | ### In allen anderen aktiven Zuständen | Zustand | Befehl | Wirkung | |---|---|---| | AUFNAHME | **„Stopp"** | Aufnahme abbrechen → LAUSCH | | GENERATOR | **„Stopp"** | Verarbeitung abbrechen → LAUSCH | | DIALOG | **„Stopp"** | Dialogfenster schließen → LAUSCH | --- ## 6. Alle Kommandozeilenoptionen ``` python3 assistant.py [OPTIONEN] ``` ### Eingabe | Option | Standard | Beschreibung | |---|---|---| | `--mic NAME` | `respeaker` | Mikrofon: `respeaker` \| `motu` \| `camera` \| `default` \| `bluetooth` \| `` \| `` | | `--list-mics` | — | Alle verfügbaren Mikrofone anzeigen und beenden | | `--silence-sec N` | `5.0` | Stille-Dauer in Sekunden bis die Aufnahme endet | | `--stop-word WORT` | `over` | Codewort zum manuellen Beenden der Aufnahme | | `--no-wakeword` | — | Wake-Word deaktivieren, sofort in AUFNAHME starten | | `--wakeword-threshold N` | `0.5` | Empfindlichkeit Wake-Word-Erkennung (0.0–1.0) | ### LLM-Backend | Option | Standard | Beschreibung | |---|---|---| | `--backend NAME` | `llama` | Backend: `llama` \| `ollama` \| `openai` | | `--model NAME` | auto | Modellname (bei llama.cpp: automatisch vom Server) | | `--system TEXT` | (eingebaut) | System-Prompt für den Assistenten | | `--history N` | `10` | Maximale Anzahl gespeicherter Gesprächsrunden | ### Spracherkennung (Whisper) | Option | Standard | Beschreibung | |---|---|---| | `--whisper-model NAME` | `large-v3` | Whisper-Modell | | `--gpu N` | `1` | CUDA-Index für Whisper (in `CUDA_VISIBLE_DEVICES`) | | `--lang CODE` | `de` | Sprache der Benutzereingabe (`de`, `en`, `fr`, …) | ### Sprachausgabe (TTS) | Option | Standard | Beschreibung | |---|---|---| | `--voice NAME` | `de_DE-thorsten-high` | Standard-Piper-Stimme (Fallback) | | `--en-variant` | `us` | Englische Variante: `us` (Ryan) \| `gb` (Alan) | | `--out NAME` | `default` | Ausgabe-Sink: `default` \| `respeaker` \| `hdmi` \| `motu` \| `bluetooth` \| `` | | `--ack-text TEXT` | `Moment, ich antworte gleich.` | Quittungssatz im GENERATOR-Zustand | | `--dialog-timeout N` | `5.0` | DIALOG-Fenster in Sekunden | ### Typische Kombinationen ```bash # Entwicklung / Debugging (kein Wake-Word, kurze Stille) python3 assistant.py --no-wakeword --silence-sec 2.0 # MOTU M2 als Mikrofon und Ausgang python3 assistant.py --mic motu --out motu # Englisch mit britischer Stimme python3 assistant.py --lang en --voice en_GB-alan-medium --en-variant gb # Empfindlicheres Wake-Word python3 assistant.py --wakeword-threshold 0.3 # Längeres Dialogfenster python3 assistant.py --dialog-timeout 10.0 ``` --- ## 7. Mikrofon wählen ```bash # Alle verfügbaren Mikrofone anzeigen python3 assistant.py --list-mics # oder python3 mic.py ``` **Vordefinierte Kurznamen:** | Kurzname | Gerät | |---|---| | `respeaker` | ReSpeaker XVF3800 (Standard) | | `motu` | MOTU M2 Mikrofon-Eingang | | `camera` | USB-Kamera-Mikrofon (VF0680) | | `default` | System-Standard-Eingabe (PipeWire) | | `bluetooth` | Erstes verbundenes Bluetooth-Gerät | Alternativ kann ein **numerischer Index** (`--mic 3`) oder ein **Substring** des Gerätenamens (`--mic "USB Audio"`) angegeben werden. --- ## 8. Audio-Ausgang wählen ```bash # Alle verfügbaren Ausgänge anzeigen python3 speak.py --list ``` **Vordefinierte Kurznamen:** | Kurzname | Gerät | |---|---| | `default` | PipeWire-Standard-Sink | | `respeaker` | ReSpeaker XVF3800 3,5-mm-Klinke | | `hdmi` | HDA NVidia HDMI | | `motu` | MOTU M2 Ausgang | | `bluetooth` | Erstes verbundenes Bluetooth-Gerät | Vollständige Sink-Namen aus `pactl list sinks short` können direkt verwendet werden. --- ## 9. LLM-Backend konfigurieren ### llama.cpp (Standard) ```bash # llama.cpp muss auf Port 8001 laufen python3 assistant.py --backend llama ``` Der Modellname wird automatisch vom Server abgefragt. ### Ollama ```bash # Ollama muss laufen: ollama serve python3 assistant.py --backend ollama --model llama3.2 python3 assistant.py --backend ollama --model mistral ``` ### OpenAI ```bash export OPENAI_API_KEY=sk-... python3 assistant.py --backend openai --model gpt-4o-mini python3 assistant.py --backend openai --model gpt-4o ``` --- ## 10. Sprache und Stimme ### Automatische Spracherkennung Der Assistent erkennt automatisch die Sprache der LLM-Antwort und wählt die passende Piper-Stimme. Fehlende Stimmen werden beim ersten Bedarf automatisch heruntergeladen. | Sprache | Stimme | |---|---| | Deutsch | `de_DE-thorsten-high` | | Englisch (US) | `en_US-ryan-high` | | Englisch (GB) | `en_GB-alan-medium` | | Französisch | `fr_FR-upmc-medium` | | Spanisch | `es_ES-davefx-medium` | | Italienisch | `it_IT-paola-medium` | | Niederländisch | `nl_NL-mls-medium` | | Portugiesisch | `pt_BR-faber-medium` | | Russisch | `ru_RU-ruslan-medium` | | Polnisch | `pl_PL-bass-high` | | Ukrainisch | `uk_UA-lada-x_low` | | Tschechisch | `cs_CZ-jirka-medium` | ### Englische Variante wählen Da automatische Erkennung nicht zwischen en-US und en-GB unterscheiden kann, wird die Variante beim Start festgelegt: ```bash python3 assistant.py --en-variant us # Standard: amerikanisches Englisch python3 assistant.py --en-variant gb # britisches Englisch ``` ### Eigene Standardstimme Die `--voice`-Option setzt die Fallback-Stimme (wenn Spracherkennung fehlschlägt oder die erkannte Sprache nicht in der Tabelle ist): ```bash python3 assistant.py --voice de_DE-kerstin-low ``` --- ## 11. Standalone-Werkzeuge ### speak.py — Sprachausgabe testen ```bash # Text vorlesen python3 speak.py --text "Hallo, ich bin dein Assistent." # Mit bestimmter Stimme und Ausgang python3 speak.py --text "Hello World" --voice en_US-ryan-high --out respeaker # Text aus stdin echo "Test" | python3 speak.py # Alle Ausgänge anzeigen python3 speak.py --list # Alle verfügbaren Piper-Stimmen (Deutsch) python3 speak.py --list-voices --voice-lang de # Alle Stimmen aller Sprachen python3 speak.py --list-voices --voice-lang "" ``` ### transcribe.py — Transkription testen ```bash # Live-Transkription mit ReSpeaker python3 transcribe.py # Mit anderem Mikrofon python3 transcribe.py --mic motu # Alle Mikrofone anzeigen python3 transcribe.py --list-mics ``` ### mic.py — Mikrofone anzeigen ```bash python3 mic.py ``` --- ## 12. Tipps und Fehlerbehebung ### Wake-Word wird nicht erkannt - Lautstärke des Mikrofons erhöhen: `pactl set-source-volume 150%` - Schwellenwert senken: `--wakeword-threshold 0.3` - Zum Testen `--no-wakeword` verwenden ### Transkription ist ungenau - Lautstärke erhöhen - Hintergrundgeräusche reduzieren - ReSpeaker XVF3800 verwenden (Hardware-AEC unterdrückt Lautsprecher-Echo) - `--lang` korrekt setzen (z. B. `--lang de` für Deutsch) ### „Stopp" wird nicht erkannt - Deutlich und mit normaler Lautstärke sprechen - Latenz: ca. 0,5–1 Sekunde bis zur Reaktion (Whisper muss verarbeiten) - In AUFNAHME: `--stop-word` ist ein anderes Wort; „Stopp" wird separat erkannt ### TTS-Stimme klingt falsch für die Sprache - Stimme wurde mit falscher Sprache verwendet (z. B. Download fehlgeschlagen) - Fehlermeldung erscheint im Terminal; nochmals versuchen (automatischer Retry 3×) - Netzwerkverbindung prüfen (Stimmen werden von HuggingFace geladen) ### Piper-Stimme fehlt / Download schlägt fehl ```bash # Verfügbare Stimmen anzeigen python3 speak.py --list-voices --voice-lang de # Stimme manuell laden (wird dann gecacht) python3 speak.py --text "Test" --voice ru_RU-ruslan-medium ``` ### audio: input overflow Diese Meldung wird bewusst unterdrückt. Sie tritt auf wenn Whisper die Verarbeitung verzögert und der PortAudio-Puffer überläuft. Das ist normal und beeinflusst die Qualität nicht wesentlich. ### llama.cpp antwortet nicht ```bash # Prüfen ob der Server läuft curl http://localhost:8001/v1/models # Modell und Port in llama.cpp-Konfiguration prüfen ```