From edd1e1d34ead5a91261000b2bfeb76b50a6cfeb3 Mon Sep 17 00:00:00 2001 From: mk Date: Mon, 23 Mar 2026 23:37:36 -0300 Subject: [PATCH] fix: start VAD gate open to avoid permanent silence on model load failure Starting the gate closed caused permanent silence if the ONNX model or WASM files failed to load (onFrameProcessed never fired). Gate now starts open so audio flows immediately; the first silence frame closes it. Also ensures the gate is always reset to open when VAD is disabled. Co-Authored-By: Claude Sonnet 4.6 --- src/livekit/SileroVADGate.ts | 7 ++++--- src/state/CallViewModel/localMember/Publisher.ts | 4 +--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/livekit/SileroVADGate.ts b/src/livekit/SileroVADGate.ts index e7bd9751..86814bcf 100644 --- a/src/livekit/SileroVADGate.ts +++ b/src/livekit/SileroVADGate.ts @@ -82,9 +82,10 @@ export class SileroVADGate { onSpeechRealStart: (): void => {}, }); - // Gate starts closed — audio is muted until the first speech frame arrives. - this.gateOpen = false; - this.onClose(); + // Gate starts OPEN so audio flows immediately. The first silence frame + // will close it. This also means a failed model load degrades gracefully + // (audio still flows) rather than permanently muting the user. + this.gateOpen = true; await this.vad.start(); log.info("MicVAD started"); diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index faed893b..77e8e419 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -454,7 +454,7 @@ export class Publisher { void vadGate.destroy(); vadGate = null; } - // Reset gate to open so audio flows if VAD is toggled off mid-call + // Always reopen gate when VAD stops so audio flows without VAD transformer?.setVADOpen(true); }; @@ -468,8 +468,6 @@ export class Publisher { } const stream = new MediaStream([rawTrack]); vadGate = new SileroVADGate(stream, ctx); - // 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) => {