Управляйте приложением React с помощью голоса

Не так давно я реализовал с помощью TensorFlowJS модель распознавания голоса. Даже несмотря на то, что задача была очень интересной, ее расширение могло вызвать затруднения. Причина же достаточно проста: для определения большего количества слов требовалась глубоко обученная модель.

Сегодня же я решил написать статью о полноценном распознавании речи для веб-приложений при помощи Web Speech API.

Прежде чем перейти к самой реализации, нужно отметить некоторые сценарии, в которых эта функциональность окажется очень кстати:

  • Создание приложения для ситуаций, когда невозможно использовать клавиатуру или сенсорные устройства. Например, люди, работающие в полях или носящие специальные перчатки, могут испытывать трудности при работе с устройствами ввода. 
  • Для поддержания людей с ограниченными возможностями.
  • Да просто потому, что это круто!

В чем секрет внедрения распознавания речи в веб-приложения?

Барабанная дробь… Секрет в Chrome (или Chromium) Web Speech API. Этот API, работающий с браузерами на основе Chromium, просто великолепен и выполняет основную работу за нас. Нам остается лишь позаботиться о создании лучших интерфейсов с использованием голосового ввода. 

Но насколько бы невероятен ни был этот API, на конец 2020 года он все еще не поддерживается обширно, что в зависимости от ваших требований может вызвать трудности. Я приведу ссылку для отслеживания его текущего статуса через ресурс Can I use. Кроме того, он функционирует только в режиме онлайн, поэтому при работе в оффлайн потребуется уже другая настройка. 

Естественно, этот API доступен через JavaScript, не является уникальным и не ограничивается React. Тем не менее существует отличная библиотека React, упрощающая его еще больше. Ее мы и будем сегодня использовать. 

Если у вас возникнет желание сделать собственную реализацию на чистом JS или в любом другом фреймворке, то рекомендую почитать документацию Speech Recognition API на MDN.

Hello World, я транскрибирую

Начнем с основ и создадим приложение Hello World, которое будет в реальном времени транскрибировать речь пользователя. Сперва нам понадобится хорошая рабочая база, поэтому первым делом настроим проект. Чтобы не усложнять, мы используем для этого create-react-app.

npx create-react-app voice-command

Далее установим библиотеку react-speech-recognition:

npm i react-speech-recognition

Затем перейдем к файлу App.js. CRA (create-react-app) создает хорошую стартовую точку. Шучу, конечно. Нам ничего из этого не понадобится, так что начнем мы с чистого App.js, который предлагаю заполнять вслед за мной.

Для начала нам понадобятся imports:

import { useEffect } from 'react';
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';

Далее создадим простой функциональный компонент, содержащий несколько кнопок для взаимодействия с движком обработки речи.

function App() {
  const { transcript } = useSpeechRecognition();

  return (
    <div>
      <h3>Hello World!</h3>
      <p>{transcript ? transcript : 'Start listening for transcript'}</p>
    
      <button onClick={SpeechRecognition.startListening}>Start listening</button>
      &nbsp;
      <button onClick={SpeechRecognition.stopListening}>Stop listening</button>
    </div>
  );
}

Выполнить все это достаточно легко. Теперь посмотрим подробнее, что именно здесь происходит, и начнем с хука useSpeechRecognition.

Этот хук отвечает за перехват результатов распознавания речи. Он будет шлюзом для генерации нужных результатов. В простейшей форме реализации можно просто извлекать transcript из произносимой пользователем речи при включенном микрофоне, что мы и делаем здесь:

const { transcript } = useSpeechRecognition();

Даже при активации этого хука мы не начинаем прослушивание сразу. Для этого нужно взаимодействовать с объектом SpeechRecognition, который мы импортировали в начале. Этот объект предлагает ряд вспомогательных методов для управления API распознавания речи, начала прослушивания микрофона, остановки, смены языков и т.д.

В итоге наш интерфейс показывает две кнопки для управления микрофоном. Если вы скопировали приведенный выше код, то выглядеть все это будет так:

Живое демо можете опробовать на Live Cose Stream

Если протестировать демо, то можно заметить, что при нажатии паузы происходит пропуск слов. Это поведение установлено библиотекой по умолчанию, но его можно изменить, настроив параметр continuous в методе startListening так:

SpeechRecognition.startListening({ continuous: true });

Определение совместимости

У нас уже получается неплохое приложение! Но что, если ваш браузер не поддерживается? Можно ли использовать для таких случаев резервный вариант поведения? Да, можно. Если вам нужно изменять поведение приложения, исходя из того, поддерживается или нет API распознавания речи, то в react-speech-recognition для этого есть специальный метод. Вот пример:

useEffect(() => {
    if (!SpeechRecognition.browserSupportsSpeechRecognition()) {
      alert("Ups, your browser is not supported!");
    }  
  }, []);

Обнаружение команд

Пока что мы рассмотрели преобразование голоса в текст. Теперь же шагнем далее и добавим в приложение распознавание предопределенных команд. Эта функциональность даст нам возможность создавать приложения, полноценно функционирующие посредством голоса.

Для написания парсера команд нам бы пришлось проделать немало работы. К счастью, в Web Speech API уже есть встроенная функциональность распознавания команд.

Вот выдержка из документации react-speech-recognition:

Чтобы отвечать на произнесение пользователем конкретной фразы, нужно передать список команд в хук useSpeechRecognition. Каждая команда является объектом со следующими свойствами:

command  —  строка или RegExp, представляющая фразу, которую нужно прослушивать.

callback  —  функция, выполняемая при произнесении команды. Последний ее аргумент всегда будет объектом, содержащим следующие свойства:

resetTranscript  —  функция, устанавливающая транскрипцию на пустую строку.

matchInterim  —  логическое значение, определяющее, нужно ли сопоставлять “interim” (промежуточные) результаты с командой. Это ускорит реагирование компонента на команды, но также увеличит вероятность ложных срабатываний  —  то есть обнаружение команды без ее произнесения. По умолчанию данный параметр установлен как false, и активировать его рекомендуется только для простых команд. 

isFuzzyMatch  —  логическое значение, определяющее, должно ли сравнение речи и command происходить на основе их схожести или исключительно на основе точности. Частичное сопоставление полезно для команд, которые легко произнести неточно, или тех, что могут быть неверно интерпретированы движком распознавания речи (например, названия мест, спортивных команд, позиций меню ресторана и т.д.). Она предназначена для команд, представляющих строковые литералы без специальных символов. Если command будет строкой со спецсимволом или RegExp, то при включении частичного совпадения она будет преобразована в строку без такого символа. Степень схожести, необходимой для сопоставления команды, можно настроить с помощью fuzzyMatchingThreshold. По умолчанию параметр isFuzzyMatch установлен как false.

fuzzyMatchingThreshold: если схожесть речи и command выше этого значения, активируется обратный вызов. Настраивать данный параметр нужно, только когда isFuzzyMatch установлен как true. Здесь можно задать десятичные значения от 0 (совпадение не требуется) до 1 (требуется точное совпадение). По умолчанию установлено 0.8.

Вот пример предопределения команд:

const commands = [
  {
    command: 'Hello',
    callback: () => alert('You just said hi!!'),
    matchInterim: true
  },
]
const { transcript } = useSpeechRecognition({ commands })

Можно также настроить динамические команды:

const commands = [
  {
    command: 'I would like to order *',
    callback: (food) => setMessage(`Your order is for: ${food}`)
  },
]
const { transcript } = useSpeechRecognition({ commands })

Заключение

Благодаря Web Speech API от Chrome, создание приложений с обработкой речи становится легким и интересным. Надеюсь, что в ближайшем будущем этот API будет поддерживаться большим числом браузеров и обзаведется оффлайн-возможностями. В этом случае он станет очень мощным инструментом, способным сильно повлиять на способ создания веб-приложений.

Благодарю за чтение!

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Juan Cruz Martinez: How to Control Your React App With Your Voice

Предыдущая статьяСделай сам  -  как автоматизировать прошивку смартфонов
Следующая статья5 минут на машинное обучение