mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
fix: voice mic race condition — onend blocks restart during TTS, clean abort+restart after speech, stuck isSpeaking watchdog
This commit is contained in:
+24
-5
@@ -1012,6 +1012,13 @@ function showApp(name, greeting, silent = false) {
|
|||||||
exitVoiceMode();
|
exitVoiceMode();
|
||||||
}
|
}
|
||||||
}, 60000);
|
}, 60000);
|
||||||
|
// Watchdog: reset isSpeaking if stuck (TTS error left it true)
|
||||||
|
setInterval(() => {
|
||||||
|
if (isSpeaking && !_ttsAudio && !window.speechSynthesis?.speaking) {
|
||||||
|
isSpeaking = false;
|
||||||
|
if (isListening) try { recognition?.start(); } catch(_) {}
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
startListening();
|
startListening();
|
||||||
loadNetwork();
|
loadNetwork();
|
||||||
loadHA();
|
loadHA();
|
||||||
@@ -1785,8 +1792,10 @@ function initVoice() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
recognition.onend = () => {
|
recognition.onend = () => {
|
||||||
// Always restart for continuous wake word / command listening
|
// Only restart when not speaking — _resumeMic() handles restart after TTS
|
||||||
if (isListening) setTimeout(() => { try { recognition.start(); } catch(_) {} }, 100);
|
if (isListening && !isSpeaking) {
|
||||||
|
setTimeout(() => { try { recognition.start(); } catch(_) {} }, 150);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
recognition.onerror = (e) => {
|
recognition.onerror = (e) => {
|
||||||
@@ -1908,8 +1917,13 @@ async function speak(text) {
|
|||||||
const _resumeMic = () => {
|
const _resumeMic = () => {
|
||||||
isSpeaking = false;
|
isSpeaking = false;
|
||||||
reactor?.classList.remove('speaking');
|
reactor?.classList.remove('speaking');
|
||||||
// Let onend restart recognition automatically (300ms buffer after audio ends)
|
if (isListening) {
|
||||||
if (isListening) setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 300);
|
// Abort any stale session then restart cleanly
|
||||||
|
setTimeout(() => {
|
||||||
|
try { recognition?.abort(); } catch(_) {}
|
||||||
|
setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 150);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/tts', {
|
const res = await fetch('/api/tts', {
|
||||||
@@ -1942,7 +1956,12 @@ function _speakFallback(text) {
|
|||||||
utter.onend = () => {
|
utter.onend = () => {
|
||||||
reactor?.classList.remove('speaking');
|
reactor?.classList.remove('speaking');
|
||||||
isSpeaking = false;
|
isSpeaking = false;
|
||||||
if (isListening) setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 300);
|
if (isListening) {
|
||||||
|
setTimeout(() => {
|
||||||
|
try { recognition?.abort(); } catch(_) {}
|
||||||
|
setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 150);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
synth.speak(utter);
|
synth.speak(utter);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user