feat(stt): bessere Spracherkennung — small-Modell, VAD, feste Sprache

Gegen "Blödsinn", v. a. an Handys:
1) Modell-Default base -> small + compute_type int8 (Benchmark auf der VM:
   base patzt schon bei sauberem Audio "an Dienstag und 10 Uhr", small korrekt
   "am Dienstag um 10 Uhr"; ~4 s/6-s-Clip, gecacht).
2) faster_whisper.transcribe mit vad_filter=True (+min_silence 500ms) und
   condition_on_previous_text=False -> weniger Stille-/Kontext-Halluzinationen.
3) stt_force_language (Default True): WS-Pfad gibt die feste Zielsprache vor
   statt Auto-Detect -> robust bei kurzen/verrauschten Clips. Auto-Detect +
   Fremdsprachen-Übersetzung jetzt opt-in (stt_force_language=False).

Tests: Config-Defaults + VAD/Language-Durchreichung; test_ws-Übersetzung auf
opt-in umgestellt. Suite 253 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 19:36:17 +02:00
commit f30b9b56c7
5 changed files with 61 additions and 12 deletions

View file

@ -212,15 +212,21 @@ async def _voice_turn(websocket, store, user, session_id, audio, fmt, options):
return
try:
# Gesprochene Sprache automatisch erkennen (egal welche). Weicht sie von der
# Zielsprache ab, wird die Anfrage in die Zielsprache übersetzt — so erscheint
# und verarbeitet das System sie immer in der eingestellten Sprache.
transcript, detected = await orchestrator.stt.transcribe_detect(
audio, fmt=fmt, language=None
)
if (transcript and transcript.strip() and detected
and detected.lower() != (route.language or "").lower()):
transcript = await orchestrator.translate(transcript, route.language)
if settings.stt_force_language:
# Feste Zielsprache statt Auto-Detect -> robuster bei kurzen/verrauschten
# (Handy-)Clips; verhindert "falsche Sprache erkannt = Blödsinn".
transcript, _ = await orchestrator.stt.transcribe_detect(
audio, fmt=fmt, language=route.language
)
else:
# Gesprochene Sprache automatisch erkennen; weicht sie von der Zielsprache
# ab, wird in die Zielsprache übersetzt (Fremdsprachen-Diktat).
transcript, detected = await orchestrator.stt.transcribe_detect(
audio, fmt=fmt, language=None
)
if (transcript and transcript.strip() and detected
and detected.lower() != (route.language or "").lower()):
transcript = await orchestrator.translate(transcript, route.language)
effective_voice = voice_for_route(route.tts_provider, route.language, route.voice_gender)
except Exception as exc:
await websocket.send_json({"type": "error", "status": 502, "detail": str(exc)})