mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
fix: mute mic during ElevenLabs TTS to prevent feedback loop; wire isSpeaking
This commit is contained in:
+19
-4
@@ -1734,6 +1734,7 @@ function initVoice() {
|
||||
recognition.lang = 'en-US';
|
||||
|
||||
recognition.onresult = (e) => {
|
||||
if (isSpeaking) return; // ignore mic during TTS playback
|
||||
const result = e.results[e.results.length - 1];
|
||||
if (!result.isFinal) return;
|
||||
const transcript = result[0].transcript.trim();
|
||||
@@ -1866,8 +1867,17 @@ async function speak(text) {
|
||||
if (!text) return;
|
||||
if (_ttsAudio) { _ttsAudio.pause(); _ttsAudio = null; }
|
||||
synth?.cancel();
|
||||
isSpeaking = true;
|
||||
// Pause recognition while JARVIS speaks to avoid mic feedback
|
||||
try { recognition?.abort(); } catch(_) {}
|
||||
const reactor = document.getElementById('arcReactor');
|
||||
reactor?.classList.add('speaking');
|
||||
const _resumeMic = () => {
|
||||
isSpeaking = false;
|
||||
reactor?.classList.remove('speaking');
|
||||
// Let onend restart recognition automatically (300ms buffer after audio ends)
|
||||
if (isListening) setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 300);
|
||||
};
|
||||
try {
|
||||
const res = await fetch('/api/tts', {
|
||||
method: 'POST',
|
||||
@@ -1878,11 +1888,11 @@ async function speak(text) {
|
||||
const blob = await res.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
_ttsAudio = new Audio(url);
|
||||
_ttsAudio.onended = () => { URL.revokeObjectURL(url); _ttsAudio = null; reactor?.classList.remove('speaking'); };
|
||||
_ttsAudio.onerror = () => { reactor?.classList.remove('speaking'); _ttsAudio = null; };
|
||||
_ttsAudio.onended = () => { URL.revokeObjectURL(url); _ttsAudio = null; _resumeMic(); };
|
||||
_ttsAudio.onerror = () => { _ttsAudio = null; _resumeMic(); };
|
||||
await _ttsAudio.play();
|
||||
} catch(e) {
|
||||
reactor?.classList.remove('speaking');
|
||||
_resumeMic();
|
||||
_speakFallback(text);
|
||||
}
|
||||
}
|
||||
@@ -1890,12 +1900,17 @@ async function speak(text) {
|
||||
function _speakFallback(text) {
|
||||
if (!synth || !text) return;
|
||||
synth.cancel();
|
||||
isSpeaking = true;
|
||||
const utter = new SpeechSynthesisUtterance(text);
|
||||
if (selectedVoice) utter.voice = selectedVoice;
|
||||
utter.rate = 0.92; utter.pitch = 0.85; utter.volume = 1;
|
||||
const reactor = document.getElementById('arcReactor');
|
||||
utter.onstart = () => reactor?.classList.add('speaking');
|
||||
utter.onend = () => reactor?.classList.remove('speaking');
|
||||
utter.onend = () => {
|
||||
reactor?.classList.remove('speaking');
|
||||
isSpeaking = false;
|
||||
if (isListening) setTimeout(() => { try { recognition?.start(); } catch(_) {} }, 300);
|
||||
};
|
||||
synth.speak(utter);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user