Falar as Palavras
O aprendiz responde a uma pergunta ou lê um prompt em voz alta. O sistema usa reconhecimento de voz para verificar a resposta falada.
Experimente
Clique no microfone e diga a palavra em voz alta: maçã.
Clique para falar
Este navegador não reconhece fala. Use o Chrome ou outro navegador baseado em Chromium para praticar esta atividade.
Código-fonte
Dados de exemplo
A palavra a ser falada e a resposta esperada, fixas no próprio arquivo.
| 1 |
<?php
|
| 2 |
$instrucao = 'Clique no microfone e diga a palavra em voz alta:';
|
| 3 |
$palavra = 'maçã';
|
| 4 |
?>
|
Estrutura da questão
Botão de microfone, status da escuta e área de avaliação.
| 1 |
<div class="questao" data-tipo="falar-palavras" data-resposta="<?= htmlspecialchars($palavra) ?>">
|
| 2 |
|
| 3 |
<p class="questao-instrucao">
|
| 4 |
<?= htmlspecialchars($instrucao) ?> <strong><?= htmlspecialchars($palavra) ?></strong>
|
| 5 |
</p>
|
| 6 |
|
| 7 |
<div class="questao-microfone">
|
| 8 |
<button type="button" class="questao-mic">Falar</button>
|
| 9 |
<p class="questao-status">Clique para falar</p>
|
| 10 |
</div>
|
| 11 |
|
| 12 |
<div class="questao-acoes">
|
| 13 |
<div class="questao-feedback" hidden></div>
|
| 14 |
<button type="button" class="questao-reset" hidden>Tentar novamente</button>
|
| 15 |
</div>
|
| 16 |
|
| 17 |
</div>
|
Instrução
Enunciado da pergunta, com a palavra-alvo em destaque.
| 1 |
.questao-instrucao {
|
| 2 |
font-size: 16px;
|
| 3 |
font-weight: 600;
|
| 4 |
margin-bottom: 20px;
|
| 5 |
line-height: 1.5;
|
| 6 |
}
|
Botão do microfone
Círculo grande — é o alvo principal da interação.
| 1 |
.questao-microfone {
|
| 2 |
display: flex;
|
| 3 |
flex-direction: column;
|
| 4 |
align-items: center;
|
| 5 |
gap: 12px;
|
| 6 |
padding: 24px 0;
|
| 7 |
}
|
| 8 |
|
| 9 |
.questao-mic {
|
| 10 |
width: 72px;
|
| 11 |
height: 72px;
|
| 12 |
border-radius: 50%;
|
| 13 |
border: 2px solid #6366f1;
|
| 14 |
background: rgba(99, 102, 241, .1);
|
| 15 |
color: #4338ca;
|
| 16 |
font: inherit;
|
| 17 |
font-weight: 600;
|
| 18 |
cursor: pointer;
|
| 19 |
}
|
| 20 |
|
| 21 |
.questao-mic:hover { background: rgba(99, 102, 241, .2); }
|
| 22 |
.questao-mic:disabled { cursor: not-allowed; opacity: .7; }
|
Estados da gravação
Vermelho durante a escuta; verde no acerto, vermelho forte no erro.
| 1 |
.questao-mic.ouvindo { border-color: #dc2626; background: rgba(220, 38, 38, .15); color: #b91c1c; }
|
| 2 |
.questao-mic.acerto { border-color: #16a34a; background: rgba(22, 163, 74, .15); color: #15803d; }
|
| 3 |
.questao-mic.erro { border-color: #dc2626; background: rgba(220, 38, 38, .15); color: #b91c1c; }
|
| 4 |
|
| 5 |
.questao-status {
|
| 6 |
font-size: 14px;
|
| 7 |
color: #64748b;
|
| 8 |
}
|
Área de ação
Reúne o resultado da avaliação e o botão de reiniciar.
| 1 |
.questao-acoes {
|
| 2 |
display: flex;
|
| 3 |
flex-direction: column;
|
| 4 |
gap: 12px;
|
| 5 |
}
|
| 6 |
|
| 7 |
.questao-feedback {
|
| 8 |
padding: 12px 16px;
|
| 9 |
border-radius: 10px;
|
| 10 |
line-height: 1.6;
|
| 11 |
}
|
| 12 |
|
| 13 |
.questao-feedback.acerto { background: #dcfce7; color: #14532d; }
|
| 14 |
.questao-feedback.erro { background: #fee2e2; color: #7f1d1d; }
|
| 15 |
|
| 16 |
.questao-reset {
|
| 17 |
width: 100%;
|
| 18 |
padding: 12px 16px;
|
| 19 |
border: none;
|
| 20 |
border-radius: 10px;
|
| 21 |
background: #e5e7eb;
|
| 22 |
color: #1f2937;
|
| 23 |
font: inherit;
|
| 24 |
font-weight: 600;
|
| 25 |
cursor: pointer;
|
| 26 |
}
|
Encontrar os elementos da questão
Localiza o microfone, o status e a área de avaliação.
| 1 |
document.addEventListener('DOMContentLoaded', function () {
|
| 2 |
document.querySelectorAll('.questao[data-tipo="falar-palavras"]').forEach(function (questao) {
|
| 3 |
var microfone = questao.querySelector('.questao-mic');
|
| 4 |
var status = questao.querySelector('.questao-status');
|
| 5 |
var feedback = questao.querySelector('.questao-feedback');
|
| 6 |
var reset = questao.querySelector('.questao-reset');
|
| 7 |
var resposta = questao.dataset.resposta;
|
Verificar suporte do navegador
Só o Chrome e outros baseados em Chromium implementam o reconhecimento de voz.
| 1 |
var Reconhecimento = window.SpeechRecognition || window.webkitSpeechRecognition;
|
| 2 |
if (!Reconhecimento) {
|
| 3 |
microfone.disabled = true;
|
| 4 |
status.textContent = 'Este navegador não reconhece fala.';
|
| 5 |
return;
|
| 6 |
}
|
Comparar a transcrição com a resposta esperada
Normaliza maiúsculas, acentos e pontuação — a API costuma devolver "Maçã." em vez de "maçã".
| 1 |
function normalizar(texto) {
|
| 2 |
return texto
|
| 3 |
.toLowerCase()
|
| 4 |
.normalize('NFD').replace(/\p{Diacritic}/gu, '')
|
| 5 |
.replace(/[^\p{L}\p{N}\s]/gu, '')
|
| 6 |
.trim();
|
| 7 |
}
|
Iniciar a gravação
Cada clique cria uma sessão nova; o próprio navegador para de ouvir depois da fala.
| 1 |
microfone.addEventListener('click', function () {
|
| 2 |
var recognition = new Reconhecimento();
|
| 3 |
recognition.lang = 'pt-BR';
|
| 4 |
|
| 5 |
recognition.onstart = function () {
|
| 6 |
microfone.classList.add('ouvindo');
|
| 7 |
status.textContent = 'Ouvindo...';
|
| 8 |
};
|
| 9 |
|
| 10 |
recognition.onresult = function (evento) {
|
| 11 |
var transcricao = evento.results[0][0].transcript;
|
| 12 |
var correta = normalizar(transcricao) === normalizar(resposta);
|
| 13 |
|
| 14 |
microfone.classList.remove('ouvindo');
|
| 15 |
microfone.classList.add(correta ? 'acerto' : 'erro');
|
| 16 |
microfone.disabled = true;
|
| 17 |
|
| 18 |
feedback.className = 'questao-feedback ' + (correta ? 'acerto' : 'erro');
|
| 19 |
feedback.textContent = correta
|
| 20 |
? 'Reconhecido! Você disse: "' + transcricao + '".'
|
| 21 |
: 'Não reconheci. Você disse: "' + transcricao + '".';
|
| 22 |
feedback.hidden = false;
|
| 23 |
reset.hidden = false;
|
| 24 |
};
|
| 25 |
|
| 26 |
recognition.onerror = function () {
|
| 27 |
microfone.classList.remove('ouvindo');
|
| 28 |
status.textContent = 'Não consegui ouvir. Clique para tentar de novo.';
|
| 29 |
};
|
| 30 |
|
| 31 |
recognition.start();
|
| 32 |
});
|
Reiniciar
Libera o microfone e limpa o resultado para uma nova tentativa.
| 1 |
reset.addEventListener('click', function () {
|
| 2 |
microfone.disabled = false;
|
| 3 |
microfone.classList.remove('acerto', 'erro');
|
| 4 |
status.textContent = 'Clique para falar';
|
| 5 |
feedback.hidden = true;
|
| 6 |
reset.hidden = true;
|
| 7 |
});
|