fix(recorder): Resolve infinite loop stale closure & reset status text on discard
This commit is contained in:
@@ -187,9 +187,10 @@ const Recorder: React.FC<RecorderProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refs for interval access to avoid dependency cycles
|
// Refs for interval access to avoid dependency cycles and stale closures
|
||||||
const lastSpeechTimeRef = useRef<number>(Date.now());
|
const lastSpeechTimeRef = useRef<number>(Date.now());
|
||||||
const isStoppingRef = useRef(false);
|
const isStoppingRef = useRef(false);
|
||||||
|
const autoStartEnabledRef = useRef(autoStartEnabled);
|
||||||
|
|
||||||
// Update refs when state changes
|
// Update refs when state changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -200,6 +201,10 @@ const Recorder: React.FC<RecorderProps> = ({
|
|||||||
isStoppingRef.current = isStopping;
|
isStoppingRef.current = isStopping;
|
||||||
}, [isStopping]);
|
}, [isStopping]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
autoStartEnabledRef.current = autoStartEnabled;
|
||||||
|
}, [autoStartEnabled]);
|
||||||
|
|
||||||
// 1. Event Listeners Effect (Run ONCE when recording starts)
|
// 1. Event Listeners Effect (Run ONCE when recording starts)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unlistenVAD: () => void;
|
let unlistenVAD: () => void;
|
||||||
@@ -348,17 +353,14 @@ const Recorder: React.FC<RecorderProps> = ({
|
|||||||
|
|
||||||
// NEW: Check if speech was actually detected during the session
|
// NEW: Check if speech was actually detected during the session
|
||||||
// If we recorded 20s of silence (Auto-Stop), we shouldn't transcribe.
|
// If we recorded 20s of silence (Auto-Stop), we shouldn't transcribe.
|
||||||
// If we recorded 20s of silence (Auto-Stop), we shouldn't transcribe.
|
// IMPORTANT: Check applies to BOTH 'voice' and 'meeting' modes to prevent "Batch Null" errors on false triggers.
|
||||||
if (!hasSpeechDetected && recordingMode === 'voice') {
|
if (!hasSpeechDetected) {
|
||||||
// Note: For 'meeting' mode, system audio might have happened without VAD triggering?
|
|
||||||
// But our updated backend VAD logic includes System Audio in 'is_speech' event.
|
|
||||||
// So we can trust hasSpeechDetected for both modes now.
|
|
||||||
|
|
||||||
console.log("No speech detected during recording. Skipping transcription.");
|
console.log("No speech detected during recording. Skipping transcription.");
|
||||||
addToast("Recording discarded (No speech/audio detected)", 'info');
|
addToast("Recording discarded (No speech/audio detected)", 'info');
|
||||||
|
setStatus('Ready to record'); // Reset status text
|
||||||
|
|
||||||
// If auto-start is on, we just loop back.
|
// If auto-start is on, we just loop back (in finally block).
|
||||||
// skip the rest.
|
// But we skip the expensive/failing API call.
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Wait a moment for file flush (safety)
|
// Wait a moment for file flush (safety)
|
||||||
@@ -489,11 +491,15 @@ const Recorder: React.FC<RecorderProps> = ({
|
|||||||
setIsStopping(false);
|
setIsStopping(false);
|
||||||
|
|
||||||
// AUTO-RESTART LOGIC
|
// AUTO-RESTART LOGIC
|
||||||
if (autoStartEnabled) {
|
// Use REF to get the latest state (fix for "starts again even if I uncheck")
|
||||||
|
if (autoStartEnabledRef.current) {
|
||||||
console.log("Auto-Start enabled: Restarting listener loop...");
|
console.log("Auto-Start enabled: Restarting listener loop...");
|
||||||
// Short delay to ensure backend cleanup
|
// Short delay to ensure backend cleanup
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
// Double check ref before restarting
|
||||||
|
if (autoStartEnabledRef.current) {
|
||||||
startRecording();
|
startRecording();
|
||||||
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user