mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(dictation): bail after worklet load if aborted; drop stale PCM on stop
Address two P2 review comments on useLocalDictation: - Recheck startAbortedRef after audioWorklet.addModule() resolves. If stop/cancel fired during the module load, the start path previously continued to wire up the worklet, start the flush timer, and set isRecording=true, leaving dictation running after it was stopped. Now bails and tears down the mic/context it opened. - Clear worklet.port.onmessage on stop/cleanup so PCM messages still queued on the main thread are dropped instead of appended to the reused audioBatchRef after the final flush. Also reset the batch on cleanup and at the start of each new recording so a stale batch can't leak into the next session/draft.
This commit is contained in:
parent
3b182acc5e
commit
79da7cddef
@@ -164,11 +164,16 @@ export function useLocalDictation({
|
||||
}
|
||||
streamRef.current = null;
|
||||
}
|
||||
// Disconnect audio worklet.
|
||||
// Disconnect audio worklet. Clear the port handler first so any PCM
|
||||
// messages still queued on the main thread are dropped instead of
|
||||
// appended to the (reused) audio batch.
|
||||
if (workletRef.current) {
|
||||
workletRef.current.port.onmessage = null;
|
||||
workletRef.current.disconnect();
|
||||
workletRef.current = null;
|
||||
}
|
||||
// Drop any audio still buffered so it can't leak into the next session.
|
||||
audioBatchRef.current = [];
|
||||
// Close audio context.
|
||||
if (audioContextRef.current) {
|
||||
void audioContextRef.current.close();
|
||||
@@ -193,6 +198,9 @@ export function useLocalDictation({
|
||||
|
||||
// Clear abort flag for this new start attempt.
|
||||
startAbortedRef.current = false;
|
||||
// Reset any leftover audio buffer so a stale batch from a prior session
|
||||
// can't be flushed into this new session/draft.
|
||||
audioBatchRef.current = [];
|
||||
|
||||
setIsStarting(true);
|
||||
onRecordingStartRef.current?.();
|
||||
@@ -316,6 +324,18 @@ export function useLocalDictation({
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
|
||||
// Bail if stop/cancel was called while the worklet module was loading.
|
||||
// Without this the worklet/flush timer would start and `isRecording`
|
||||
// would be set true, leaving dictation running after it was stopped.
|
||||
if (startAbortedRef.current) {
|
||||
for (const track of stream.getTracks()) track.stop();
|
||||
streamRef.current = null;
|
||||
void audioContext.close();
|
||||
audioContextRef.current = null;
|
||||
invoke("stop_dictation").catch(() => {});
|
||||
return;
|
||||
}
|
||||
|
||||
const source = audioContext.createMediaStreamSource(stream);
|
||||
const worklet = new AudioWorkletNode(audioContext, "dictation-processor");
|
||||
workletRef.current = worklet;
|
||||
@@ -382,6 +402,10 @@ export function useLocalDictation({
|
||||
streamRef.current = null;
|
||||
}
|
||||
if (workletRef.current) {
|
||||
// Clear the port handler so PCM messages still queued on the main
|
||||
// thread are dropped rather than appended to the batch after the
|
||||
// final flush below (and leaking into the next session).
|
||||
workletRef.current.port.onmessage = null;
|
||||
workletRef.current.disconnect();
|
||||
workletRef.current = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user