Spec-Zone.ru › Web APIs

Использование Web Speech API

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

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

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

Web Speech API имеет главный контроллер для этого — SpeechRecognition — плюс ряд тесно связанных интерфейсов для представления грамматики, результатов и т. д. Как правило, для распознавания речи используется стандартная система распознавания речи, доступная на устройстве — большинство современных операционных систем имеют систему распознавания речи для выдачи голосовых команд. Подумайте о функции «Диктовка» в macOS, Siri в iOS, Cortana в Windows 10, Android Speech и т. д.

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

Демо

Чтобы продемонстрировать простое использование распознавания речи Web Speech, мы написали демонстрацию под названием Смена цвета с помощью речи. При нажатии/щелчке по экрану вы можете произнести ключевое слово HTML-цвета, и цвет фона приложения изменится на этот цвет.

The UI of an app titled Speech Color changer. It invites the user to tap the screen and say a color, and then it turns the background of the app that color. In this case it has turned the background red.

Чтобы запустить демонстрацию, перейдите по ссылке на демонстрацию в поддерживаемом мобильном браузере (например, Chrome).

HTML и CSS

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

<h1>Speech color changer</h1>
<p>Tap/click then say a color to change the background color of the app.</p>
<div>
  <p class="output"><em>…diagnostic messages</em></p>
</div>

CSS предоставляет очень простую адаптивную стилизацию, чтобы приложение выглядело хорошо на разных устройствах.

JavaScript

Давайте рассмотрим JavaScript более подробно.

Префиксные свойства

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

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

Грамматика

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

const colors = [
  "aqua",
  "azure",
  "beige",
  "bisque",
  "black",
  "blue",
  "brown",
  "chocolate",
  "coral" /* … */,
];
const grammar = `#JSGF V1.0; grammar colors; public <color> = ${colors.join(
  " | ",
)};`;

Используемый формат грамматики — JSpeech Grammar Format (JSGF) — вы можете узнать больше об этом по ссылке на спецификацию. Однако пока давайте быстро пройдёмся по ней:

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

Включение грамматики в распознавание речи

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

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

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

speechRecognitionList.addFromString(grammar, 1);

Затем мы добавляем SpeechGrammarList в экземпляр распознавания речи, установив его в значение свойства SpeechRecognition.grammars. Мы также устанавливаем несколько других свойств экземпляра распознавания перед продолжением:

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

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

После получения ссылок на выходной <div> и элемент HTML (так что мы можем выводить диагностические сообщения и обновлять цвет фона приложения позже), мы реализуем обработчик onclick, чтобы при нажатии/щелчке на экран служба распознавания речи запускалась. Это достигается вызовом SpeechRecognition.start(). Метод forEach() используется для вывода цветных индикаторов, показывающих, какие цвета следует попробовать произнести.

const diagnostic = document.querySelector(".output");
const bg = document.querySelector("html");
const hints = document.querySelector(".hints");

let colorHTML = "";
colors.forEach((color, i) => {
  console.log(color, i);
  colorHTML += `<span style="background-color:${color};"> ${color} </span>`;
});
hints.innerHTML = `Tap or click then say a color to change the background color of the app. Try ${colorHTML}.`;

document.body.onclick = () => {
  recognition.start();
  console.log("Ready to receive a color command.");
};

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

После запуска распознавания речи можно использовать много обработчиков событий для извлечения результатов и других фрагментов связанной информации (см. события SpeechRecognition). Наиболее часто используемым, вероятно, будет событие result, которое срабатывает после получения успешного результата:

recognition.onresult = (event) => {
  const color = event.results[0][0].transcript;
  diagnostic.textContent = `Result received: ${color}.`;
  bg.style.backgroundColor = color;
  console.log(`Confidence: ${event.results[0][0].confidence}`);
};

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

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

recognition.onspeechend = () => {
  recognition.stop();
};

Обработка ошибок и нераспознанной речи

Последние два обработчика предназначены для обработки случаев, когда распознанная речь не была в определенной грамматике или произошла ошибка. Событие nomatch должно обрабатывать первый упомянутый случай, хотя обратите внимание, что в данный момент оно, похоже, не срабатывает должным образом; оно просто возвращает то, что было распознано:

recognition.onnomatch = (event) => {
  diagnostic.textContent = "I didn't recognize that color.";
};

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

recognition.onerror = (event) => {
  diagnostic.textContent = `Error occurred in recognition: ${event.error}`;
};

Синтез речи

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

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

Демо

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

UI of an app called speak easy synthesis. It has an input field in which to input text to be synthesized, slider controls to change the rate and pitch of the speech, and a drop down menu to choose between different voices.

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

HTML и CSS

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

<h1>Speech synthesizer</h1>

<p>
  Enter some text in the input below and press return to hear it. Change voices
  using the dropdown menu.
</p>

<form>
  <input type="text" class="txt" />
  <div>
    <label for="rate">Rate</label
    ><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate" />
    <div class="rate-value">1</div>
    <div class="clearfix"></div>
  </div>
  <div>
    <label for="pitch">Pitch</label
    ><input type="range" min="0" max="2" value="1" step="0.1" id="pitch" />
    <div class="pitch-value">1</div>
    <div class="clearfix"></div>
  </div>
  <select></select>
</form>

JavaScript

Давайте рассмотрим JavaScript, который питает это приложение.

Установка переменных

Прежде всего, мы получаем ссылки на все элементы DOM, участвующие в пользовательском интерфейсе, но более интересно, мы получаем ссылку на Window.speechSynthesis. Это точка входа API — она возвращает экземпляр SpeechSynthesis, интерфейс-контроллер для синтеза речи в браузере.

const synth = window.speechSynthesis;

const inputForm = document.querySelector("form");
const inputTxt = document.querySelector(".txt");
const voiceSelect = document.querySelector("select");

const pitch = document.querySelector("#pitch");
const pitchValue = document.querySelector(".pitch-value");
const rate = document.querySelector("#rate");
const rateValue = document.querySelector(".rate-value");

const voices = [];

Заполнение элемента select

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

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

function populateVoiceList() {
  voices = synth.getVoices();

  for (const voice of voices) {
    const option = document.createElement("option");
    option.textContent = `${voice.name} (${voice.lang})`;

    if (voice.default) {
      option.textContent += " — DEFAULT";
    }

    option.setAttribute("data-lang", voice.lang);
    option.setAttribute("data-name", voice.name);
    voiceSelect.appendChild(option);
  }
}

Старые браузеры не поддерживают событие voiceschanged, и просто возвращают список голосов при вызове SpeechSynthesis.getVoices(). В то время как в других, таких как Chrome, необходимо подождать, пока событие не сработает, прежде чем заполнять список. Чтобы учесть оба случая, мы выполняем функцию, как показано ниже:

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

Произнесение введенного текста

Далее, мы создаем обработчик событий для начала произнесения текста, введенного в поле ввода. Мы используем обработчик onsubmit в форме, чтобы действие происходило при нажатии Enter/Return. Сначала мы создаем новый экземпляр SpeechSynthesisUtterance() с помощью его конструктора — в него передается значение ввода текста в качестве параметра.

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

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

inputForm.onsubmit = (event) => {
  event.preventDefault();

  const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
  const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
  for (const voice of voices) {
    if (voice.name === selectedOption) {
      utterThis.voice = voice;
    }
  }
  utterThis.pitch = pitch.value;
  utterThis.rate = rate.value;
  synth.speak(utterThis);

В заключительной части обработчика мы включаем событие pause, чтобы продемонстрировать, как можно использовать SpeechSynthesisEvent с пользой. При вызове SpeechSynthesis.pause() возвращается сообщение с номером и именем символа, на котором было приостановлено произношение.

utterThis.onpause = (event) => {
  const char = event.utterance.text.charAt(event.charIndex);
  console.log(
    `Speech paused at character ${event.charIndex} of "${event.utterance.text}", which is "${char}".`,
  );
};

Наконец, мы вызываем blur() на поле ввода текста. Это в основном для скрытия клавиатуры в Firefox OS.

  inputTxt.blur();
}

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

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

pitch.onchange = () => {
  pitchValue.textContent = pitch.value;
};

rate.onchange = () => {
  rateValue.textContent = rate.value;
};

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API