Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Эта страница была переведена с английского языка силами сообщества. Вы тоже можете внести свой вклад, присоединившись к русскоязычному сообществу MDN Web Docs.

Применение Web Speech API

Web Speech API предоставляет 2 основных типа функциональности —распознавание речи пользователя иречевое воспроизведение текста. Это предоставляет новые возможности для взаимодействия с интерфейсом и открывает перед нами новые горизонты создания уникального пользовательского опыта. Эта статья даёт краткое описание обоих направлений с примерами кода и ссылкой на работающее приложение онлайн.

Распознавание речи

Механизм распознавания речи способен принимать речевой поток через микрофон устройства, а затем проверять его, используя свои внутренние алгоритмы. Для более точной работы рекомендуется использовать интерфейсSpeechGrammar, предоставляющий контейнер для определённого набора грамматики, которое ваше приложение должно использовать. Грамматика определяется с помощьюJSpeech Grammar Format(JSGF.).

После того, как пользовательская речь была распознана, алгоритм возвращает результат (список результатов) в качестве текстовой строки, с которой мы можем продолжить работу.

Примечание:В Chrome распознавание речи на веб-странице завязано на взаимодействие с сервером. Ваш звук отправляется на веб-службу для обработки распознавания, поэтому приложение не будет работать в офлайн-режиме.

Демо

Демонстрацию использования распознавания речи можно увидеть в приложенииSpeech color changer. При клике по экрану можно произнести название цвета, и фон приложения изменится на этот цвет.

Пользовательский интерфейс приложения Speech Color changer. Он предлагает пользователю нажать на экран и произнести цвет, а затем окрашивает фон приложения в этот цвет. В данном случае фон стал красным.

Для запуска демонстрации откройтестраницу приложения в браузере мобильного устройства с поддержкой распознавания речи (например, в Chrome).

HTML и CSS

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

CSS задаёт простые отзывчивые стили, для корректного отображения и работы на всех устройствах

JavaScript

А вот на реализацию логики давайте обратим более пристальное внимание.

Поддержка Chrome

Как уже упоминалось ранее, в настоящее время Chrome поддерживает интерфейс распознавания речи с указанными префиксами, поэтому в начале нашего кода мы включаем строки префиксов для использования нужных объектов в Chrome и ссылки на объекты без префиксов для Firefox.

const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;const SpeechGrammarList = window.SpeechGrammarList || window.webkitSpeechGrammarList;const SpeechRecognitionEvent = window.SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent;

Грамматика

Следующая часть нашего кода определяет грамматику, которую мы хотим, применять для поиска соответствий.

Определяем следующие переменные:

const colors = {  красный: 'red',  оранжевый: 'orange',  жёлтый: 'yellow',  зелёный: 'green',  голубой: 'blue',  синий: 'darkblue',  фиолетовый: 'violet'};const colorsList = Object.keys(colors);const grammar = '#JSGF V1.0; grammar colors; public <color> = ' + colorsList.join(' | ') + ' ;';Формат “грамматики“ используемой нами - это JSpeech Grammar Format (JSGF) - по ссылке можете почитать про это больше.

Быстро пробежимся по основным принципам:

  • Линии разделены точкой с запятой, как и в JavaScript.
  • Первая строка -#JSGF V1.0; - указывает формат и версию. Это всегда необходимо включать в первую очередь.
  • Вторая строка указывает значение, которое мы хотим распознать. public объявляет, что это общедоступное правило, строка в угловых скобках определяет распознанное имя для этого значения (цвет), а список элементов, следующих за знаком равенства, - это альтернативные варианты, которые будут распознаны и могут быть приняты в качестве возможного значения. Обратите внимание, как каждый из них разделяется вертикальной линией ("|" - "pipe character").
  • У вас может быть множество значений, определённых отдельно, как указано выше, и содержащих довольно сложные определения грамматики. Для нашего демонстрационного примера мы делаем все просто.

Подключение грамматики к нашему распознаванию речи

Следующее, что нужно сделать, это определить экземпляр объекта распознавания речи для управления записью нашего приложения.

Это делается с помощью конструктораSpeechRecognition(). Мы также создаём новый речевой грамматический список, чтобы содержать нашу грамматику, используя конструкторSpeechGrammarList().

const recognition = new SpeechRecognition();const speechRecognitionList = new SpeechGrammarList();

Добавляем нашу "грамматику" в список, используя методSpeechGrammarList.addFromString(). Он принимает в качестве параметров строку, плюс необязательное значение веса, которое указывает важность этой грамматики по отношению к другим грамматикам, доступным в списке (может быть от 0 до 1 включительно). Добавленная грамматика доступна в списке как экземпляр объектаSpeechGrammar.

js
speechRecognitionList.addFromString(grammar, 1);

Затем мы добавляемSpeechGrammarList к уже созданному объекту распознавания речи, присваивая его значение свойствуSpeechRecognition.grammars. Также зададим ещё несколько свойств объекту, прежде чем двигаться дальше:

  • SpeechRecognition.lang: устанавливает язык распознавания. Его установка - это хорошая практика, поэтому рекомендуется не пропускать.
  • SpeechRecognition.interimResults: определяет, должна ли система распознавания речи возвращать промежуточные результаты или только конечные результаты. Только конечные результаты подойдут для этой нашего простого приложения.
  • SpeechRecognition.maxAlternatives: устанавливает количество альтернативных потенциальных совпадений, которые должны быть возвращены на каждый результат. Иногда это может быть полезно, скажем, если результат распознан не точно, и вы хотите отобразить пользователю список вариантов. Но это для простого примера это не нужно, поэтому мы просто указываем один (который по сути является вариантом по умолчанию).
js
recognition.grammars = speechRecognitionList;//recognition.continuous = false;recognition.lang = "ru-RU";recognition.interimResults = false;recognition.maxAlternatives = 1;

Примечание:SpeechRecognition.continuous задаёт, отслеживаются ли продолжающиеся результаты или только 1 результат, каждый раз, когда запись начата. Это закомментировано, поскольку данное свойство в ещё не реализовано в Gecko.

Вы можете получить аналогичный результат, просто прекратив распознавание после получения первого результата.

Запуск распознавания речи

После получения ссылок на DOM-элементы, необходимые нам для обработки пользовательских событий и обновления цвета фона приложения, мы реализуем обработчикonclick, чтобы при нажатии на значок микрофона сервис распознавания речи начинал работу. Запуск происходит путём вызова функцииSpeechRecognition.start().

microphoneIcon.onclick = function() {  recognition.start();  console.log('Ready to receive a color command.');};recognition.onaudiostart = function() {  microphoneWrapper.style.visibility = 'hidden';  audioRecordAnimation.style.visibility = 'visible';};

Получение и обработка результата

После того, как процесс распознавания речи был запущен, есть много обработчиков событий, которые могут быть использованы для работы с результатом и другой сопутствующей информацией (см.Список обработчиков событий SpeechRecognition.) Наиболее распространённый, который вы, вероятно, и будете использовать, этоSpeechRecognition.onresult, который запускается сразу после получения успешного результата. Значение цвета получаем вызовом функцииgetColor()

function getColor(speechResult) {  for (let index = 0; index < colorsList.length; index += 1) {    if (speechResult.indexOf(colorsList[index]) !== -1) {      const colorKey = colorsList[index];      return [colorKey, colors[colorKey]];    }  }  return null;}recognition.onresult = function(event) {  const last = event.results.length - 1;  const colors = getColor(event.results[last][0].transcript);  recognitionTextResult.textContent = 'Результат: ' + colors[0];  speechRecognitionSection.style.backgroundColor = colors[1];  console.log('Confidence: ' + event.results[0][0].confidence);};

Третья строка здесь выглядит немного усложнённой, поэтому давайте разберёмся с ней подробнее. СвойствоSpeechRecognitionEvent.results возвращает объектSpeechRecognitionResultList, содержащий в себе другие объекты типаSpeechRecognitionResult. У него есть геттер, поэтому он может быть доступен как массив, поэтому переменнаяlast определяет ссылку наSpeechRecognitionResult из списка. Каждый объектSpeechRecognitionResult содержит объектыSpeechRecognitionAlternative, которые содержат отдельные распознанные слова. Они также имеют геттеры, поэтому к ним можно получить доступ как к массивам, поэтому логично, что [0] возвращает значениеSpeechRecognitionAlternative по индексу 0. Затем мы возвращаем строку, содержащую индивидуально распознанный результат, используя который и можем установить цвет фона.

Мы также используем свойствоSpeechRecognition.speechend, чтобы задать обработчик на завершение работы распознавателя речи (вызовSpeechRecognition.stop() ), как только одно слово было распознано, и входящий речевой поток был остановлен.

recognition.onspeechend = function() {  recognition.stop();  microphoneWrapper.style.visibility = 'visible';  audioRecordAnimation.style.visibility = 'hidden';};

Обработка ошибок

Последние два обработчика используются для отлова ошибок: когда речь была признана не в соответствии с определённой грамматикой или произошла ошибка. По логике,SpeechRecognition.onnomatch, должен обрабатывать первый случай, но обратите внимание, что на данный момент он не срабатывает правильно в Firefox или Chrome, он просто возвращает все, что было распознано в любом случае:

recognition.onnomatch = function(event) {  alert("I didn't recognise that color.");};

SpeechRecognition.onerror обрабатывает случаи, когда имела место быть фактическая ошибка при распознавании. СвойствоSpeechRecognitionError.error содержит возвращаемую фактическую ошибку:

recognition.onerror = function(event) {  alert(`Error occurred in recognition: ${event.error}`);};

Синтез речи

Синтез речи (text-to-speech или tts) подразумевает получение синтезированного текста приложения и его речевое воспроизведение.

Для этой цели Web Speech API предоставляет интерфейс -SpeechSynthesis - плюс ряд близких интерфейсов для нужного нам воспроизведения текста (utterances - "дикция"), набор голосов, которыми приложение будет "говорить", и т. д.Опять же, большинство ОС имеют некоторые встроенные системы синтеза речи, которые будут задействованы нашим API для этой цели.

Демо

Демонстрацию использования синтеза речи можно увидеть в приложенииSpeak easy synthesis. Оно содержит набор элементов управления формой для ввода текста, который будет синтезирован, и настройки высоты тона, скорости и голоса, которые будут использоваться при произнесении текста. После ввода текста можно нажатьEnter/Return, чтобы услышать его.

Пользовательский интерфейс приложения Speak easy synthesis. Он имеет поле ввода текста для синтеза, ползунки для изменения скорости и высоты тона речи, а также выпадающее меню для выбора между различными голосами.

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

HTML и CSS

HTML и CSS снова достаточно тривиальны.Заголовок и форму с некоторыми простыми элементами управления.Элемент<select> изначально пуст, но заполняется с помощью<option> через JavaScript (см. ниже).

CSS задаёт простые отзывчивые стили, для корректного отображения и работы на всех устройствах

<section>  <h1>Синтез речи</h1>  <p>Введите текст в поле ниже и нажмите кнопку "Play", чтобы прослушать запись. Выбирайте возможные голоса из списка ниже</p>  <form>    <input type="text">    <div>      <div>        <div>          <div>Темп (Rate)</div>          <div>1</div>        </div>        <div>          <div>Диапазон (Pitch)</div>          <div>1</div>        </div>      </div>      <div>        <input type="range" min="0.5" max="2" value="1" step="0.1">        <input type="range" min="0" max="2" value="1" step="0.1">      </div>    </div>    <select>    </select>    <button type="submit">Play</button>  </form>

JavaScript

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

Задание переменных

Прежде всего, создаём ссылки на все нужные нам DOM-элементы.

Входная точка API -window.speechSynthesis, возвращает экземплярSpeechSynthesis, интерфейс контроллера для синтеза речи в вебе.

const synth = window.speechSynthesis;const inputForm = document.querySelector('form');const inputTxt = document.querySelector('.text');const voicesList = document.querySelector('select');const pitch = document.querySelector('#pitch');const pitchValue = document.querySelector('.value--pitch-value');const rate = document.querySelector('#rate');const rateValue = document.querySelector('.value--rate-value');let voices = [];

Заполнение выпадающего списка

Чтобы заполнить элемент<select> различными вариантами голоса, доступных на устройстве, напишем функциюpopulateVoiceList(). Сначала мы вызываемSpeechSynthesis.getVoices(), который возвращает список всех доступных вариантов голосов, представленных объектамиSpeechSynthesisVoice. Затем мы проходимся по списку, создавая элемент<option> для каждого отдельного случая, задаём его текстовое содержимое, соответствующее названию голоса (взято изSpeechSynthesisVoice.name), языка голоса (изSpeechSynthesisVoice.lang), и "по умолчанию", если голос является голосом по умолчанию для механизма синтеза (проверяется, если функцияSpeechSynthesisVoice.default возвращает значениеtrue.)

Мы также задаёмdata- атрибуты для каждого варианта, содержащие имя и язык связанного голоса, благодаря чему мы можем легко их собрать их позже, а затем вложить все варианты в качестве дочерних элементов нашего списка (<select>).

function populateVoiceList() {  voices = synth.getVoices();  const selectedIndex =  voicesList.selectedIndex < 0 ? 0 : voicesList.selectedIndex;  voicesList.innerHTML = '';  for(i = 0; i < voices.length ; i++) {    const option = document.createElement('option');    option.textContent = voices[i].name + ' (' + voices[i].lang + ')';    if(voices[i].default) {      option.textContent += ' -- DEFAULT';    }    option.setAttribute('data-lang', voices[i].lang);    option.setAttribute('data-name', voices[i].name);    voiceSelect.appendChild(option);  }  voicesList.selectedIndex = selectedIndex;}

Когда мы собираемся запустить функцию, мы делаем следующее. Это связано с тем, что Firefox не поддерживает свойствоSpeechSynthesis.onvoiceschanged и будет только возвращать список голосов при запускеSpeechSynthesis.getVoices(). Однако, в Chrome вам нужно дождаться триггера события перед заполнением списка, следовательно, нужно условие, описанное в блоке сif ниже.

populateVoiceList();  if (speechSynthesis.onvoiceschanged !== undefined) {  speechSynthesis.onvoiceschanged = populateVoiceList;}

Озвучка введённого текста

Затем мы создаём обработчик событий, чтобы начать "произносить" текст, введённый в текстовом поле, при нажатии на кнопкуEnter/Return или наPlay. Для этого используем обработчикonsubmit в html-формы. В функции-обработчикеspeak() мы создаём новый экземплярSpeechSynthesisUtterance(), передавая значение текстового поля в конструктор.

Затем нам нужно выяснить, какой голос использовать. Мы используем свойствоHTMLSelectElementselectedOptions для получения выбранного элемента<option>, у которого берём атрибут data-name, и находим объектSpeechSynthesisVoice, имя которого соответствует значению имеющегося атрибута. После этого устанавливаем соответствующий "голосовой" объект как значение свойстваSpeechSynthesisUtterance.voice.

Наконец, мы устанавливаемSpeechSynthesisUtterance.pitch (высота тона) иSpeechSynthesisUtterance.rate (скорость) в соответствии со значениями соответствующих элементов формы. Затем, после всего проделанного, мы запускаем произношение речи, вызываяSpeechSynthesis.speak(), и передавая ему экземплярSpeechSynthesisUtterance в качестве аргумента.

Внутри функцииspeak() мы выполняем проверку на то, воспроизводится ли речь в данный момент, с помощью свойстваSpeechSynthesis.speakingЕсли да, то останавливаем процесс функциейSpeechSynthesis.cancel() и запускаем рекурсивно заново.

В последней части функции мы включаем обработчикSpeechSynthesisUtterance.onpause, чтобы показать пример примененияSpeechSynthesisEvent в различных ситуациях. ВызовSpeechSynthesis.pause()возвращает сообщение с информацией о номере символа и слове, на котором была вызвана пауза.

Наконец, мы назовёмblur() у текстового поля. Это, прежде всего, для того, чтобы скрыть клавиатуру в ОС Firefox.

js
function speak() {  if (synth.speaking) {    console.error("speechSynthesis.speaking");    synth.cancel();    setTimeout(speak, 300);  } else if (inputTxt.value !== "") {    const utterThis = new SpeechSynthesisUtterance(inputTxt.value);    utterThis.onend = function (event) {      console.log("SpeechSynthesisUtterance.onend");    };    utterThis.onerror = function (event) {      console.error("SpeechSynthesisUtterance.onerror");    };    const selectedOption =      voicesList.selectedOptions[0].getAttribute("data-name");    for (i = 0; i < voices.length; i++) {      if (voices[i].name === selectedOption) {        utterThis.voice = voices[i];      }    }    utterThis.onpause = function (event) {      const char = event.utterance.text.charAt(event.charIndex);      console.log(        "Speech paused at character " +          event.charIndex +          ' of "' +          event.utterance.text +          '", which is "' +          char +          '".',      );    };    utterThis.pitch = pitch.value;    utterThis.rate = rate.value;    synth.speak(utterThis);  }}inputForm.onsubmit = function (event) {  event.preventDefault();  speak();  inputTxt.blur();};

Обновление отображаемых значений высоты тона и скорости

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

js
pitch.onchange = function () {  pitchValue.textContent = pitch.value;};rate.onchange = function () {  rateValue.textContent = rate.value;};

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp