diff --git a/bridge/server.py b/bridge/server.py index 55827a1..50e24f6 100644 --- a/bridge/server.py +++ b/bridge/server.py @@ -209,12 +209,16 @@ def transcribe(wav_bytes: bytes) -> dict: return {"text": "", "language": None} segments, info = _whisper.transcribe(audio, beam_size=1) - # Second line of defence: even speech-like audio (e.g. a clap the VAD let - # through) can make Whisper hallucinate, so drop non-speech / low-confidence - # segments by Whisper's own no_speech_prob + avg_logprob. Mirrors the desktop - # listener's policy, driven by the same config thresholds. - no_speech_threshold = getattr(_cfg, "whisper_no_speech_threshold", 0.5) - min_confidence = getattr(_cfg, "whisper_min_confidence", 0.3) + # Second line of defence: drop non-speech / hallucinated segments by + # Whisper's own no_speech_prob. The no_speech_prob hard cutoff (plus the VAD + # pre-gate above) is what rejects noise/hallucinations. The avg_logprob + # CONFIDENCE floor is deliberately OFF by default (STT_MIN_CONFIDENCE=0): + # short, accented, or quiet real speech over a Discord mic scores very low + # avg_logprob (e.g. the wake word "자비스" at 0.0-0.3) and a confidence floor + # silently eats it, making the bot need many tries to hear one utterance. + # Raise STT_MIN_CONFIDENCE only if hallucinations slip past the no_speech gate. + no_speech_threshold = float(os.environ.get("STT_NO_SPEECH_THRESHOLD", str(getattr(_cfg, "whisper_no_speech_threshold", 0.5)))) + min_confidence = float(os.environ.get("STT_MIN_CONFIDENCE", "0.0")) kept = filter_speech_segments( segments, no_speech_threshold=no_speech_threshold,