Reconhecimento de voz NATIVO com Javascript – Dica rápida

Tempo de leitura 4 minutos

Sério, ESSA FEATURE É MUITO LEGAL, nessa dica rápida quero mostrar na prática como você pode implementar reconhecimento de voz com Javascript em seus projetos web ou aonde implementar HTML5 (Ionic, Cordova, Quasar, Electron…) sem NENHUMA api externa, nativo e muito simples.

E para demonstrar o recurso eu criei um teste “para o mundo real” aqui no blog mesmo.

Para saber do que eu estou falando você vai fazer o seguinte, na barra lateral direita você vai:

  1. Clicar no campo de pesquisa
  2. Um ícone de microfone vai aparecer
  3. Autorizar no navegador
  4. O ícone de microfone fica vermelho quando for para você falar
  5. Diga um termo que você queira pesquisar (PHP, por exemplo)
  6. Ver o resultado da pesquisa
Reconhecimento de voz aqui no blog

O recurso nada mais faz do que pegar o que foi dito e converter em texto que pode ser usado COMO VOCÊ quiser, no exemplo eu usei para fazer uma busca aqui no blog.

Para este exemplo eu quero:

  • Não me importar com navegadores antigos, eu não ligo pra eles aqui no blog, sorry!
  • Que o ícone de microfone não apareça logo de cara, somente ao clicar no input
  • Que o ícone fique vermelho quando estiver gravando o áudio
  • Que você não fique pirado em eu gravar o que você fala depois de autorizar, se for esse seu caso desautorize no navegador e fique em paz, eu não ligo pra sua vida.

Estou fornecendo a seguir o CSS e o SVG que vou usar para o front-end.

.microphone {
    background-color: black;
    -webkit-mask: url(microphone.svg) no-repeat center;
    mask: url(microphone.svg) no-repeat center;
    width: 18px;
    height: 18px;
    display: inline-block;
    cursor: pointer;
    margin-left: -35px;
    vertical-align: middle;
}

/* Para ficar vermelho quando começar a gravar */
.microphone.started {
    background-color: red;
}

Esse é o ícone do microfone, crie um arquivo chamado microphone.svg e coloque o código dentro.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 512 512">
  <g>
    <g>
      <path d="m439.5,236c0-11.3-9.1-20.4-20.4-20.4s-20.4,9.1-20.4,20.4c0,70-64,126.9-142.7,126.9-78.7,0-142.7-56.9-142.7-126.9 0-11.3-9.1-20.4-20.4-20.4s-20.4,9.1-20.4,20.4c0,86.2 71.5,157.4 163.1,166.7v57.5h-23.6c-11.3,0-20.4,9.1-20.4,20.4 0,11.3 9.1,20.4 20.4,20.4h88c11.3,0 20.4-9.1 20.4-20.4 0-11.3-9.1-20.4-20.4-20.4h-23.6v-57.5c91.6-9.3 163.1-80.5 163.1-166.7z"/>
      <path d="m256,323.5c51,0 92.3-41.3 92.3-92.3v-127.9c0-51-41.3-92.3-92.3-92.3s-92.3,41.3-92.3,92.3v127.9c0,51 41.3,92.3 92.3,92.3zm-52.3-220.2c0-28.8 23.5-52.3 52.3-52.3s52.3,23.5 52.3,52.3v127.9c0,28.8-23.5,52.3-52.3,52.3s-52.3-23.5-52.3-52.3v-127.9z"/>
    </g>
  </g>
</svg>

Eu criei um diretório chamado speech e 3 arquivos dentro:

  • microphone.svg (passei o conteúdo acima)
  • style.css (passei o conteúdo acima)
  • script.js (vem logo a seguir)

E no mesmo nível do diretório speech, um arquivo index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="speech/style.css">
</head>
<body>
    <form>
        <input type="search" class="search-field" placeholder="Pesquisar …" value="" name="s">
    </form>

    <script src="/speech/script.js"></script>
</body>
</html>

E finalmente, vamos ao script Javascript, eu comentei bem o código, então não vou entrar muito em detalhes

/**
 * Instancio o SpeechRecognition (que faz o reconhecimento de voz)
 * 
 * O correto seria usar apenas SpeechRecognition const recognition =  new SpeechRecognition
 * mas o próprio Google Chrome não da suporte correto ainda, então eu fiz algo para
 * melhorar o suporte usando o webkitSpeechRecognition quando o SpeechRecognition
 * não estiver disponível
 */
const recognition = typeof SpeechRecognition === 'undefined' ? new webkitSpeechRecognition : new SpeechRecognition;

/**
 * Se realmente não tiver suporte, bora estourar um erro
 */
if (!recognition) {
    throw new Error('SpeechRecognition is not supported');
}

// Pego o campo que vai ser usado na busca
const input = document.querySelector('input.search-field');

// Crio um elemento HTML (um node é o termo correto)
const span = document.createElement('span');

// adiciono a classe css para o botão ser renderizado
span.classList.add('microphone');

// crio uma variável para controlar o estado iniciado/parado da gravação
let recognitionStarted =  false;

// a classe css que vai mudar a cor do microfone
const spanStartedStyle  = 'started';

// o onaudiostart é um evento, ele é executado quando começa a gravação
recognition.onaudiostart = () => {
    // altera a variável de estado de gravação para indicar que começou a gravar o áudio
    recognitionStarted = true;
    // adicionar a classe para mudar a cor de indicação do microfone
    span.classList.add(spanStartedStyle);
}

// o onaudioend é um evento, ele é executado quando termina a gravação
recognition.onaudioend = () => {
    // altera a variável de estado de gravação para indicar que parou de gravar o áudio
    recognitionStarted = false;
    // remove a classe para mudar a cor de indicação do microfone
    span.classList.remove(spanStartedStyle);
}

// quando eu clicar no campo
input.addEventListener('click', (e) => {
    const { target } = e;
    const { parentElement } = target;

    /**
     * Adiciono o meu elemento (o microfone que criei acima) ao DOM
     * quer dizer que vou escrever o Node como HTML e exibir ele
     * ele vai aparecer DENTRO do elemento pai do input
     */
    parentElement.appendChild(span);

    // Quando clicar no ícone de microfone
    span.addEventListener('click', (e) => {
        // verifique se NÃO está gravando
        if (!recognitionStarted) {
            // inicio a gravação
            recognition.start();
        } else {
            // se estiver gravando eu paro de gravar
            recognition.stop();
        }
    });

    // o onresult é um evento, ele é executado quando temos uma gravação
    recognition.onresult = (event) => {
        // pego o áudio já convertido em texto
        const { transcript } = event.results[0][0];

        // adiciono ao campo como valor
        target.value = transcript;
        // pego o formulário, pai do campo clicado
        const form = target.closest('form');
        // envio o formulário
        form.submit();
    }
});

Aqui também tem um exemplo BEM legal, mudar a cor de fundo da página usando está mesma API do HTML 5, além disso é uma doc bem mais completa do que eu mostrei aqui.

https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition

É isso, só queria deixar a dica da feature pra vocês.

Se quiser ser avisado quando novos artigos sairem, cadastre-se a seguir:

Autor: Erik Figueiredo

Músico, gamer amador, tutor de programação, desenvolvedor freelancer full cycle, com foco em PHP (Laravel e CakePHP), Javascript (Front e Node.js), Dart (Front e Flutter) e infra.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *