fix: dynamischer STT-Timeout — whisper Modell-Download nicht abkappen

aria-bridge horcht jetzt auf service_status fuer den Service 'whisper'.
Solange whisper-bridge im 'loading' steckt (Erst-Download large-v3 kann
1-2 Min dauern), gilt fuer stt_request ein Timeout von 300s statt 45s.
Sobald 'ready', zurueck auf 45s — reicht selbst fuer lange Audios.

Symptom vorher: Beim ersten Sprechen nach Container-Restart hat aria-
bridge nach 45s aufgegeben und lokal gefallback waehrend whisper-bridge
noch fleissig den Download laufen hatte. Damit wurde der Sinn der
Auslagerung kaputt gemacht.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck 2026-04-24 17:06:04 +02:00
parent a361015ff4
commit 37c5f6c368
1 changed files with 30 additions and 4 deletions

View File

@ -544,6 +544,10 @@ class ARIABridge:
# STT-Requests die aktuell auf Antwort von der whisper-bridge (Gamebox) warten. # STT-Requests die aktuell auf Antwort von der whisper-bridge (Gamebox) warten.
# requestId → Future mit dem Text (oder None bei Fehler). # requestId → Future mit dem Text (oder None bei Fehler).
self._pending_stt: dict[str, asyncio.Future] = {} self._pending_stt: dict[str, asyncio.Future] = {}
# whisper-bridge service_status: True wenn ready, False/None wenn loading/unbekannt.
# Beeinflusst das Timeout fuer stt_request — bei "loading" warten wir laenger,
# weil das Modell beim ersten Request noch ~1-2 Min runtergeladen werden kann.
self._remote_stt_ready: bool = False
def initialize(self) -> None: def initialize(self) -> None:
"""Initialisiert alle Komponenten. """Initialisiert alle Komponenten.
@ -1442,13 +1446,30 @@ class ARIABridge:
future.set_result(text) future.set_result(text)
return return
elif msg_type == "service_status":
# Gamebox-Bridges (whisper / f5tts) melden ihren Lade-Status.
# Wir nutzen das fuer den dynamischen STT-Timeout: solange whisper
# im 'loading' steckt, geben wir der Bridge mehr Zeit (Modell-Download
# kann 1-2 Min dauern), statt nach 45s lokal zu fallbacken.
svc = payload.get("service", "")
state = payload.get("state", "")
if svc == "whisper":
was_ready = self._remote_stt_ready
self._remote_stt_ready = (state == "ready")
if self._remote_stt_ready != was_ready:
logger.info("[rvs] whisper-bridge -> %s", state)
return
else: else:
logger.debug("[rvs] Unbekannter Typ: %s", msg_type) logger.debug("[rvs] Unbekannter Typ: %s", msg_type)
# STT-Orchestrierung: zuerst Remote (Gamebox), Fallback lokal. # STT-Orchestrierung: zuerst Remote (Gamebox), Fallback lokal.
# Timeout grosszuegig gewaehlt, damit auch ein erstmaliger Modell-Load # Zwei Timeouts:
# auf der Gamebox (bis ~30s bei large-v3) durchgeht. # ready=True → 45s reicht selbst fuer lange Audios
_STT_REMOTE_TIMEOUT_S = 45.0 # ready=False → 300s, weil das Modell evtl. noch heruntergeladen wird
# (large-v3 ~3GB, kann auf der Gamebox 1-2 Min dauern).
_STT_REMOTE_TIMEOUT_READY_S = 45.0
_STT_REMOTE_TIMEOUT_LOADING_S = 300.0
async def _process_app_audio(self, audio_b64: str, mime_type: str) -> None: async def _process_app_audio(self, audio_b64: str, mime_type: str) -> None:
"""App-Audio → STT → aria-core. Primaer via whisper-bridge (RVS), Fallback lokal.""" """App-Audio → STT → aria-core. Primaer via whisper-bridge (RVS), Fallback lokal."""
@ -1514,7 +1535,12 @@ class ARIABridge:
if not ok: if not ok:
logger.warning("[rvs] stt_request konnte nicht gesendet werden — skip Remote") logger.warning("[rvs] stt_request konnte nicht gesendet werden — skip Remote")
return None return None
return await asyncio.wait_for(future, timeout=self._STT_REMOTE_TIMEOUT_S) timeout_s = (self._STT_REMOTE_TIMEOUT_READY_S
if self._remote_stt_ready
else self._STT_REMOTE_TIMEOUT_LOADING_S)
logger.info("[rvs] STT-Timeout %ds (whisper-bridge %s)",
int(timeout_s), "ready" if self._remote_stt_ready else "loading")
return await asyncio.wait_for(future, timeout=timeout_s)
except asyncio.TimeoutError: except asyncio.TimeoutError:
logger.warning("[rvs] Remote-STT Timeout (%.0fs)", self._STT_REMOTE_TIMEOUT_S) logger.warning("[rvs] Remote-STT Timeout (%.0fs)", self._STT_REMOTE_TIMEOUT_S)
return None return None