feat: Barge-in/Turn-Manager und VAD-Aeusserungserkennung (#4 Ausbau)

- Barge-in: Antwort-Turn als abbrechbarer asyncio.Task; {"type":"interrupt"} oder
  neue Eingabe bricht laufende Antwort ab -> interrupted-Event (/ws/chat + /ws/voice)
- VAD (app/audio/vad.py): energie-basierte Stille-Erkennung (reines Python, int16-PCM)
- /ws/voice opt-in {"type":"start","vad":true}: automatisches Aeusserungsende ohne end
- Tests: 52 gruen (+5: VAD-Unit, Barge-in, VAD-Auto-Segmentierung)
- Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur)

Offen (schwere Deps/Dienste): echte partielle Live-Transkripte (Streaming-STT),
WebRTC (aiortc). STT laeuft heute pro Aeusserung.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-17 05:06:58 +02:00
commit 093da817d8
6 changed files with 312 additions and 48 deletions

View file

@ -280,7 +280,12 @@ Satz fertig ist.
**Sprach-Eingang** (`/ws/voice`): Mikrofon-Audio als binäre Frames senden, dann
`{"type":"end"}`. Der Server schickt ein `transcript`-Event und danach die Antwort
wie bei `/ws/chat` (`stream`/`audio_stream` im `end`-Frame möglich).
wie bei `/ws/chat` (`stream`/`audio_stream` im `end`-Frame möglich). Mit
`{"type":"start","vad":true,"format":"pcm","sample_rate":16000}` erkennt der Server
das Äußerungsende automatisch an einer Sprechpause (kein `end` nötig).
**Unterbrechen (Barge-in):** Während der Assistent antwortet, `{"type":"interrupt"}`
senden — die laufende Antwort wird abgebrochen (`interrupted`-Event).
> **Für lokale Entwicklung** ist in der mitgelieferten `.env` `AUTH_ENABLED=false`
> gesetzt — dann ist kein Token nötig (anonymer Nutzer).