fix(voice): verlorene Sprachnachrichten — Allow-List, Kaltstart, Dedup, Voice-Router
Vier unabhaengige Ursachen fuer 'erst beim zweiten Aufnehmen' bzw. 'wird gar
nicht verarbeitet' (server-/box-seitig, ohne App-Update wirksam):
1) rvs/server.js: stt_lease, stt_lease_request, stt_transcribe_blob,
stt_transcribe_result und chat_ack fehlten in ALLOWED_TYPES und wurden STILL
verworfen (dieselbe Falle wie bei worker_*/host_*). Folgen: das Lease lief
immer in den 250ms-Timeout -> jede Aufnahme startete verspaetet und OHNE
targetInstance nahmen alle STT-Worker dieselbe Session an (doppelte
stt_endpoint); chat_ack kam nie an -> getippte Nachrichten galten in der App
nach 3 Versuchen als fehlgeschlagen, obwohl sie verarbeitet waren.
2) xtts/whisper/bridge.py: Beim Kaltstart wurde die Session erst NACH dem
Modell-Load angelegt — alle Chunks der ersten Aufnahme liefen ins Leere und
der Take war weg (die zweite klappte, weil das Modell dann warm war). Session
wird jetzt sofort angelegt, der Endpointer wartet solange (runner.model None).
3) bridge/aria_bridge.py: Text-Dedup-Fenster 5s -> 1.5s. Es soll nur den
Zwilling zweier Worker abfangen; mit 5s fielen echte Wiederholungen weg —
also genau das Nachsprechen nach einem verschluckten Take, und kurze
Kommandos ('lauter', 'nächstes').
4) bridge/aria_bridge.py Voice-Router: Komma als Prefix-Trenner entfernt (nur
noch ':' und '-'), Fuzzy-Schwelle 0.6 -> 0.82, Sticky wird nicht mehr bei
jeder Nachricht verlaengert. Vorher matchten normale Saetze wie 'In Ordnung,
mach mal ...' als Projekt-Prefix: die Nachricht landete still in einem
Projekt und war im Hauptchat unsichtbar — verifiziert mit Beispielsaetzen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+15
-6
@@ -584,6 +584,12 @@ class SessionManager:
|
||||
if ws is None:
|
||||
return # disconnected — Endpointer pausiert bis Reconnect
|
||||
|
||||
# Modell laedt noch (Kaltstart): Audio weiter sammeln, aber NICHT
|
||||
# transkribieren/finalisieren — sonst kaeme leerer Text heraus und die
|
||||
# Aufnahme waere verloren. Sobald es geladen ist, laeuft es normal weiter.
|
||||
if self.runner.model is None:
|
||||
return
|
||||
|
||||
audio_ms = self._buffer_duration_ms(sess)
|
||||
|
||||
# Hard-Cap erreicht → wie Endpoint behandeln (egal ob neuer Text)
|
||||
@@ -962,19 +968,22 @@ async def run_loop(runner: WhisperRunner, sessions: SessionManager) -> None:
|
||||
# transcribe-Call mit Leerstring weil Model None.
|
||||
target_model = payload.get("model") or runner.model_size or WHISPER_MODEL
|
||||
needs_load = (runner.model is None) or (target_model != runner.model_size)
|
||||
# WICHTIG: Session SOFORT anlegen — auch wenn das Modell
|
||||
# noch laedt. Sonst laufen alle stt_audio_chunk der ersten
|
||||
# Aufnahme ins Leere (feed_chunk findet keine Session) und
|
||||
# der Take ist verloren; erst die zweite Aufnahme klappt,
|
||||
# weil das Modell dann warm ist. Der Buffer fuellt sich
|
||||
# jetzt waehrend des Ladens, das Transkribieren wartet.
|
||||
sessions.start_session(payload)
|
||||
if needs_load:
|
||||
async def _load_then_start(p, target):
|
||||
async def _load_only(target):
|
||||
await _broadcast_status(ws, "loading", model=target)
|
||||
try:
|
||||
await runner.ensure_loaded(target)
|
||||
await _broadcast_status(ws, "ready", model=runner.model_size)
|
||||
except Exception as e:
|
||||
await _broadcast_status(ws, "error", error=str(e)[:200])
|
||||
return
|
||||
sessions.start_session(p)
|
||||
asyncio.create_task(_load_then_start(payload, target_model))
|
||||
else:
|
||||
sessions.start_session(payload)
|
||||
asyncio.create_task(_load_only(target_model))
|
||||
|
||||
elif mtype == "stt_audio_chunk":
|
||||
ok = sessions.feed_chunk(payload)
|
||||
|
||||
Reference in New Issue
Block a user