diff --git a/xtts/voxtral/bridge.py b/xtts/voxtral/bridge.py index b051148..ef75f1e 100644 --- a/xtts/voxtral/bridge.py +++ b/xtts/voxtral/bridge.py @@ -168,6 +168,11 @@ class StreamSession: noise_floor: float = 0.0 closed: bool = False endpoint_sent: bool = False + # Einmaliges "Sprache erkannt"-Signal an die App gesendet? Voxtral schickt + # keine Live-Partials, aber der App-No-Speech-Watchdog wartet auf ein + # stt_partial, um "der User redet" zu erkennen — sonst cancelt er mitten im + # Satz. Wir feuern EIN leeres stt_partial beim ersten Voice-Frame. + speech_signaled: bool = False # Speaker-ID Gating (einmalig auf die ersten ~1.5s der Aufnahme) speaker_checked: bool = False speaker_match: Optional[bool] = None @@ -361,6 +366,20 @@ class SessionManager: rms = self._tail_rms(sess) if rms >= self._voice_threshold(sess): sess.last_voice_at = now + # Einmalig der App melden, dass Sprache begonnen hat. Ohne Live-Partials + # wuerde ihr No-Speech-Watchdog die Aufnahme sonst am Konversations- + # fenster canceln, obwohl der User noch redet (Stefans Reproduktion: + # "beendet nach ~4s, obwohl ich weiterrede — nur im Ohr-Modus"). Ein + # leeres stt_partial reicht: die App setzt streamGotPartial=true und + # loescht den Watchdog. Nach der Speaker-ID-Pruefung (oben) → fremde + # Stimmen signalisieren NICHT. + if not sess.speech_signaled and self._ws is not None: + sess.speech_signaled = True + await _send(self._ws, "stt_partial", { + "requestId": sess.request_id, + "audioRequestId": sess.audio_request_id, + "text": "", + }) else: self._update_noise_floor(sess, rms) # Endpoint: hat der User schon gesprochen UND ist es seit endpoint_ms still?