From c82616ebbd9bc4d539620071171e249f5b7fe0ac Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 16 Aug 2026 19:38:38 +0200 Subject: [PATCH] =?UTF-8?q?fix(voxtral):=20No-Speech-Timeout=20=E2=80=94?= =?UTF-8?q?=20Stille-Fenster=20schlie=C3=9Ft=20selbst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stefans Repro: "die Stille-Ende wird nie erreicht, stop ich selbst ist es weg, und geht automatisch auf lausche Computer". Ursache: der Endpoint feuert nur wenn schon Stimme da war (last_voice_at>0). Bei totaler Stille bleibt last_voice_at==0 → Endpoint feuert NIE → Fenster offen bis Hardcap/manuellem Stop (→ stream_end → Phantom). Fix: No-Speech-Timeout im _tick — wenn nach endpoint_ms (Stille-Toleranz) ab Start noch KEINE Stimme kam, schließt der Bridge das Fenster selbst als no-speech (leer, lautlos, zurück aufs Wake-Word). voiced_frames==0 → _finalize verwirft ohne Transkript, also kein Phantom. Logik gegen totale Stille / Sprache-dann-still / Dauer-Sprache verifiziert. Co-Authored-By: Claude Opus 4.8 --- xtts/voxtral/bridge.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xtts/voxtral/bridge.py b/xtts/voxtral/bridge.py index e1d2a1c..47d67f9 100644 --- a/xtts/voxtral/bridge.py +++ b/xtts/voxtral/bridge.py @@ -428,6 +428,17 @@ class SessionManager: }) else: self._update_noise_floor(sess, rms) + # No-Speech-Timeout: wurde die GANZE Zeit KEINE Stimme erkannt + # (last_voice_at==0), feuert der normale Endpoint unten NIE — der braucht + # last_voice_at>0. Ohne das bleibt ein reines Stille-Fenster offen bis + # Hardcap/manuellem Stop → genau Stefans Repro: "die Stille-Ende wird nie + # erreicht, stop ich selbst ist es weg". Nach endpoint_ms Stille ab Start + # schliessen wir das Fenster selbst als no-speech (leer, lautlos, zurueck + # aufs Wake-Word). voiced_frames==0 → _finalize verwirft ohne Transkript, + # also KEIN Phantom. + if sess.last_voice_at == 0 and (now - sess.started_at) * 1000.0 >= sess.endpoint_ms: + await self._finalize(sess, "no_speech") + return # Endpoint: hat der User schon gesprochen UND ist es seit endpoint_ms still? if sess.last_voice_at > 0 and (now - sess.last_voice_at) * 1000.0 >= sess.endpoint_ms: await self._finalize(sess, "endpoint")