🎤 feat: Sistema de conversa por voz - auto-TTS quando mensagem vem do microfone, envio automático, melhor visibilidade do ícone
This commit is contained in:
+24
-3
@@ -288,6 +288,7 @@ const initApp = () => {
|
||||
// Variáveis de Reconhecimento de Voz
|
||||
let recognition = null;
|
||||
let isListening = false;
|
||||
let lastInputWasVoice = false; // Rastrear se a última mensagem veio do microfone
|
||||
|
||||
// ==========================================================================
|
||||
// THEME TOGGLE — Claro/Escuro
|
||||
@@ -488,13 +489,14 @@ const initApp = () => {
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// VOZ — WEB SPEECH API (ditado)
|
||||
// VOZ — WEB SPEECH API (ditado + conversa por voz)
|
||||
// ==========================================================================
|
||||
|
||||
const initVoiceRecognition = () => {
|
||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||
if (!SpeechRecognition) {
|
||||
btnVoice.style.display = 'none';
|
||||
console.warn('SpeechRecognition não suportado neste navegador.');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -509,6 +511,16 @@ const initApp = () => {
|
||||
userInput.value = transcript;
|
||||
userInput.dispatchEvent(new Event('input'));
|
||||
setVoiceState(false);
|
||||
|
||||
// Marca que o input veio do microfone para auto-responder por voz
|
||||
lastInputWasVoice = true;
|
||||
|
||||
// Envia automaticamente a mensagem ditada
|
||||
if (transcript.trim()) {
|
||||
setTimeout(() => {
|
||||
chatForm.dispatchEvent(new Event('submit', { cancelable: true }));
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
recognition.onerror = (event) => {
|
||||
@@ -525,10 +537,10 @@ const initApp = () => {
|
||||
isListening = listening;
|
||||
if (listening) {
|
||||
btnVoice.classList.add('listening');
|
||||
btnVoice.setAttribute('title', 'Clique para parar');
|
||||
btnVoice.setAttribute('title', 'Clique para parar de ouvir');
|
||||
} else {
|
||||
btnVoice.classList.remove('listening');
|
||||
btnVoice.setAttribute('title', 'Ditar mensagem');
|
||||
btnVoice.setAttribute('title', 'Conversar por voz');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1685,6 +1697,15 @@ const initApp = () => {
|
||||
|
||||
scrollToBottom();
|
||||
|
||||
// AUTO-TTS: Se a mensagem veio do microfone, ler a resposta em voz alta automaticamente
|
||||
if (lastInputWasVoice && assistantContent && !isMediaResponse) {
|
||||
console.log('[VOZ] Mensagem veio do microfone — respondendo por voz automaticamente.');
|
||||
setTimeout(() => {
|
||||
speakText(assistantContent, speakBtn);
|
||||
}, 400);
|
||||
}
|
||||
lastInputWasVoice = false;
|
||||
|
||||
// Salvar resposta no estado e localStorage
|
||||
const assistantMsg = { role: 'assistant', content: assistantContent };
|
||||
chat.messages.push(assistantMsg);
|
||||
|
||||
+10
-7
@@ -1223,10 +1223,11 @@ code {
|
||||
.btn-voice {
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
color: var(--text-muted) !important;
|
||||
color: var(--text-secondary, #a3a3a3) !important;
|
||||
border-radius: 50% !important;
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
min-width: 36px !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -1237,17 +1238,19 @@ code {
|
||||
}
|
||||
|
||||
.btn-voice svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.btn-voice:hover {
|
||||
color: var(--text-primary) !important;
|
||||
transform: scale(1.05);
|
||||
color: var(--brand-green, #10a37f) !important;
|
||||
background-color: rgba(16, 163, 127, 0.1) !important;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.btn-voice.listening {
|
||||
color: #ef4444 !important;
|
||||
background-color: rgba(239, 68, 68, 0.12) !important;
|
||||
animation: pulse-voice 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user