fix: switch VAD gate to per-frame probability control

onSpeechStart/onSpeechEnd fire at segment boundaries — with constant
non-speech noise, onSpeechEnd never fires so the gate stayed open.
Switch to onFrameProcessed which fires every ~96ms and applies hysteresis
(open at >0.5, close at <0.35) matching Silero's own thresholds. Gate now
starts closed and opens only once the first speech frame is confirmed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mk
2026-03-23 23:34:08 -03:00
parent 428b76db25
commit 9f5b639190
2 changed files with 42 additions and 26 deletions

View File

@@ -468,8 +468,10 @@ export class Publisher {
}
const stream = new MediaStream([rawTrack]);
vadGate = new SileroVADGate(stream, ctx);
vadGate.onSpeechStart = (): void => transformer?.setVADOpen(true);
vadGate.onSpeechEnd = (): void => transformer?.setVADOpen(false);
// Close the gate immediately — VAD will open it once speech is confirmed.
transformer?.setVADOpen(false);
vadGate.onOpen = (): void => transformer?.setVADOpen(true);
vadGate.onClose = (): void => transformer?.setVADOpen(false);
vadGate.start().catch((e: unknown) => {
this.logger.error("[VAD] failed to start", e);
});