Commit graph

13 commits

Author SHA1 Message Date
Dieter Schlüter
9d0019274a feat(voice_loop): --voice-Option + saubere Default-Stimme je TTS-Provider
- voice_loop.py: --voice reicht die Stimme im Start-Frame durch (nur wenn gesetzt),
  sonst greift der Provider-Default. Beispiele in Docstring/Help.
- ws.py/speak.py/chat.py: ohne explizite Stimme None durchreichen statt die
  OpenRouter-Stimme zu erzwingen -> jeder Provider nimmt SEINEN Default
  (OPENROUTER_TTS_VOICE bzw. PIPER_VOICE). Ungenutzten settings-Import in speak.py
  entfernt.
- Doku: BEDIENUNGSANLEITUNG (--voice + Default-Stimme je Provider).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:42:23 +02:00
Dieter Schlüter
37b14773f2 feat(tools): scripts/add_pronunciation.py zum bequemen Pflegen des Aussprache-Lexikons
Fuegt 'wort:aussprache' in config/pronunciation.<lang>.yaml ein (Default Sektion
terms). Erhaelt Kommentare/Struktur, aktualisiert vorhandene Eintraege statt zu
duplizieren, validiert das YAML vor dem Schreiben. Optional --verify zeigt die
espeak-Phoneme vorher/nachher und warnt, wenn die Umschreibung nichts aendert.
Doku-Hinweis in BEDIENUNGSANLEITUNG ergaenzt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:25:49 +02:00
Dieter Schlüter
84d6ac6e7b fix(voice_loop): 1011-Keepalive-Timeout bei langen Antworten beheben
Empfang und Echtzeit-Wiedergabe entkoppeln: ein _player_feeder spielt PCM-
Haeppchen aus einer asyncio.Queue ab, der Empfangs-Loop legt nur per put_nowait
ab und drainiert die WebSocket-Verbindung durchgehend. Vorher blockierte das
Schreiben in den Player (Echtzeit, voller Puffer) den Empfangs-Loop -> Frames
stauten sich -> websockets pausierte per Backpressure den Reader -> Pings/Pongs
unbearbeitet -> 1011 keepalive ping timeout (trat bei langen Antworten auf).
Zusaetzlich defensiv: ping_timeout=60, max_queue=None.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:46:19 +02:00
Dieter Schlüter
7c1f00662c feat: Audio-Streaming als Default (Admin abschaltbar via AUDIO_STREAM_DEFAULT)
- Config audio_stream_default=True; _run_turn nutzt es, wenn die Anfrage audio_stream
  nicht explizit setzt (explizite Anfrage gewinnt)
- voice_loop: immer durchgehender Player (spielt 1 oder N Haeppchen luekenlos);
  --stream-audio / --no-stream-audio als Tri-State (sonst entscheidet der Server-Default)
- conftest: audio_stream_default=False fuer deterministische Tests; neuer Test fuer
  Default-an-Streaming ueber /ws/voice; 67 Tests gruen
- Doku + .env.example aktualisiert (AUDIO_STREAM_DEFAULT, --no-stream-audio)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 18:07:36 +02:00
Dieter Schlüter
5296459b07 feat(voice_loop): --stream-text (Antworttext live am Monitor)
- neuer Flag --stream-text setzt stream:true im /ws/voice-Start-Frame;
  token-Events werden inline ausgegeben (Wort fuer Wort, waehrend die KI generiert)
- mit --stream-audio kombinierbar; bei semantic wird die Live-Zeile abgeschlossen
- Token-Events sind winzig -> Audio-Startzeit praktisch unveraendert (gemessen:
  Text 1. Token lokal ~1 s, Cloud ~3 s; erster Ton wie zuvor)
- Test: /ws/voice mit stream:true liefert token-Events; 66 Tests gruen
- Doku ergaenzt (Optionen + Feature-Hinweis)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 17:47:11 +02:00
Dieter Schlüter
ced63bac4c feat(voice_loop): --stream-audio (satzweises Vorlesen waehrend der Generierung)
- neuer Flag --stream-audio setzt audio_stream:true im /ws/voice-Start-Frame
- durchgehender Roh-PCM-Player (ffplay/aplay/paplay), Haeppchen werden sofort
  eingespeist -> Antwort beginnt nach dem ersten Satz, nicht erst nach der ganzen
- Schreiben via asyncio.to_thread (Event-Loop bleibt frei -> kein Keepalive-Timeout);
  Player wird nach Verbindungsschluss geleert
- ohne Flag unveraendert (komplettes Audio nach Verbindungsschluss)
- Doku-Hinweis ergaenzt; live verifiziert (STT lokal + LLM lokal + TTS remote, satzweise)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 17:16:05 +02:00
Dieter Schlüter
b75382e055 ux(voice_loop): Aufnahmedauer anzeigen + korrekt berechnen; Diagnose-Skript
- record_utterance zeigt nach der Aufnahme die Dauer
- Dauer aus tatsaechlicher Datenmenge statt WAV-Header (arecord schreibt beim
  Stoppen per Signal eine falsche Header-Laenge -> sonst absurde Werte wie 67108s)
- scripts/diag_record.py: Countdown + gruenes Signal -> Aufnahme -> sofort
  transkribieren (Standard + vad_filter) zur Pausen-Diagnose

Diagnose-Ergebnis: Mehrsatz-Aeusserungen mit Pausen werden vollstaendig erkannt
(Aufnahme + faster-whisper verlieren nichts) - im kontrollierten Test und im
echten voice_loop-Flow bestaetigt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 15:53:51 +02:00
Dieter Schlüter
e1167951e1 ux(voice_loop): harmlose arecord-EINTR-Meldung beim Stoppen unterdruecken
Das Stoppen per SIGINT loest in arecord ein erwartetes EINTR aus
("Unterbrechung während des Betriebssystemaufrufs"). Recorder-stderr wird nun
abgefangen und nur noch bei tatsaechlich fehlgeschlagener Aufnahme (leere Datei)
angezeigt. Die Aufnahme selbst war/ist korrekt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 11:08:08 +02:00
Dieter Schlüter
4254475b73 fix(voice_loop): Keepalive-Timeout (1011) bei langer Aufnahme/Wiedergabe behoben
Eine Dauerverbindung wurde vom Server geschlossen, wenn Aufnahme/Wiedergabe den
Event-Loop blockierten (Keepalive-Ping unbeantwortet) - sichtbar bei langen
TTS-Antworten. Jetzt: kurze WebSocket-Verbindung PRO Sprech-Runde; das Audio wird
erst NACH dem Schliessen abgespielt. Gespraechsgedaechtnis bleibt serverseitig via
session_id erhalten. Verifiziert mit langer Antwort (~12 s Audio) ohne Abbruch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 11:00:13 +02:00
Dieter Schlüter
98706ef3ec docs+ux(voice_loop): klarer Hinweis auf ALSA-Direktgeraet bei Aufnahme-Fehler
Auf PipeWire-Systemen kann der pw-record/ALSA-default-Pfad scheitern
("pw_context_connect() failed"). Direkter Zugriff via arecord -D plughw:KARTE,0
funktioniert. voice_loop gibt bei leerer Aufnahme jetzt diesen konkreten Tipp aus;
Bedienungsanleitung entsprechend ergaenzt (Recorder-Hinweis + Troubleshooting).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:44:48 +02:00
Dieter Schlüter
d15e51eb0d fix(voice_loop): PipeWire-Aufnahme (pw-record) als Standard via --recorder auto
- arecord scheiterte auf PipeWire-Systemen ("Fehler beim Öffnen des Gerätes")
- neue Option --recorder {auto,pw-record,parecord,arecord}; auto bevorzugt pw-record
- geraetespezifische Flags je Werkzeug (-D / --target / --device)
- Doku: Recorder-Hinweis + Troubleshooting-Eintrag fuer den arecord-Fehler
- verifiziert: auto -> pw-record; --file-Round-Trip weiterhin ok

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:37:49 +02:00
Dieter Schlüter
7896f608fb docs: Bedienungsanleitung (Sprech-Loop, Einstellungen, Praxis-Tests) + voice_loop.py
- NEU scripts/voice_loop.py: Mikrofon -> /ws/voice -> Wiedergabe im Loop, mit
  Gedaechtnis (--session), Geraete-/Provider-Optionen, --file fuer Test ohne Mikrofon
- BEDIENUNGSANLEITUNG.md neu strukturiert:
  Teil A (sprechen->hoeren->sprechen: voice_loop + manueller Loop + chat_client),
  Teil B (Einstellungen: KI/Provider auf allen Ebenen real; Sound-Quelle/-Ausgabe
  ehrlich auf OS-Ebene, Gateway-Endpunkte als vorbereitete Routing-Ebene),
  Teil C (Praxis-Tests + gemessene Reaktionszeiten: STT ~1,2s / LLM ~0,7s / TTS ~1,9s
  / Round-Trip ~4s; Konstellations-Empfehlung)
- Alle JSON-Befehle mit '| jq'; Audio-Befehle in Datei + Player
- README: kurzer Verweis auf den Sprech-Loop
- live verifiziert (make smoke, Timings, voice_loop --file); 64 Tests gruen

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:31:35 +02:00
Dieter Schlüter
7b1acd774d test: manuelles End-to-End-Smoke-Skript gegen OpenRouter (scripts/smoke_e2e.py)
- prueft LLM, TTS und STT live (inkl. TTS->STT-Round-Trip); klare [OK]/[FAIL]-Ausgabe
- bewusst ausserhalb von tests/ (pytest sammelt es nicht ein); macht echte Netz-Aufrufe
- Makefile-Target `make smoke`; Doku in README + BEDIENUNGSANLEITUNG
- live ausgefuehrt: LLM/TTS/STT alle bestanden

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 09:49:04 +02:00