From a6e402d6c995b0084d0fbbafba9fb7ac58cc1792 Mon Sep 17 00:00:00 2001 From: John Matthew Tennant Date: Thu, 23 Jul 2026 17:59:54 -0400 Subject: [PATCH] Fix dictation audio worklet capture (#2632) Co-authored-by: Claude Opus 4.8 (1M context) --- .../dictation/hooks/useLocalDictation.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/desktop/src/features/dictation/hooks/useLocalDictation.ts b/desktop/src/features/dictation/hooks/useLocalDictation.ts index 979862a53..a8b2aea3f 100644 --- a/desktop/src/features/dictation/hooks/useLocalDictation.ts +++ b/desktop/src/features/dictation/hooks/useLocalDictation.ts @@ -82,6 +82,7 @@ export function useLocalDictation({ const streamRef = useRef(null); const audioContextRef = useRef(null); const workletRef = useRef(null); + const outputGainRef = useRef(null); const batchTimerRef = useRef | null>(null); const audioBatchRef = useRef([]); // Tail of the serialized flush chain. Each flush appends its IPC work to @@ -257,6 +258,10 @@ export function useLocalDictation({ workletRef.current.disconnect(); workletRef.current = null; } + if (outputGainRef.current) { + outputGainRef.current.disconnect(); + outputGainRef.current = null; + } // Drop any audio still buffered so it can't leak into the next session. audioBatchRef.current = []; // Close audio context. @@ -375,6 +380,10 @@ export function useLocalDictation({ workletRef.current.disconnect(); workletRef.current = null; } + if (outputGainRef.current) { + outputGainRef.current.disconnect(); + outputGainRef.current = null; + } audioBatchRef.current = []; if (audioContextRef.current) { void audioContextRef.current.close(); @@ -479,9 +488,13 @@ export function useLocalDictation({ // Start the batch flush timer (~10 IPC calls/s instead of ~375). batchTimerRef.current = setInterval(flushAudioBatch, AUDIO_BATCH_MS); + const outputGain = audioContext.createGain(); + outputGain.gain.value = 0; + outputGainRef.current = outputGain; + source.connect(worklet); - // Don't connect to destination — we only capture, not play back. - worklet.connect(audioContext.createGain()); // keep worklet alive without audible output + worklet.connect(outputGain); + outputGain.connect(audioContext.destination); setIsRecording(true); setIsTranscribing(true); @@ -548,6 +561,10 @@ export function useLocalDictation({ workletRef.current.disconnect(); workletRef.current = null; } + if (outputGainRef.current) { + outputGainRef.current.disconnect(); + outputGainRef.current = null; + } if (audioContextRef.current) { void audioContextRef.current.close(); audioContextRef.current = null;