From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- files/ru/web/api/web_speech_api/index.html | 176 +++++++++ .../using_the_web_speech_api/index.html | 416 +++++++++++++++++++++ 2 files changed, 592 insertions(+) create mode 100644 files/ru/web/api/web_speech_api/index.html create mode 100644 files/ru/web/api/web_speech_api/using_the_web_speech_api/index.html (limited to 'files/ru/web/api/web_speech_api') diff --git a/files/ru/web/api/web_speech_api/index.html b/files/ru/web/api/web_speech_api/index.html new file mode 100644 index 0000000000..3398c86aad --- /dev/null +++ b/files/ru/web/api/web_speech_api/index.html @@ -0,0 +1,176 @@ +--- +title: Web Speech API +slug: Web/API/Web_Speech_API +translation_of: Web/API/Web_Speech_API +--- +
{{DefaultAPISidebar("Web Speech API")}}{{seecompattable}}
+ +
+

Web Speech API позволяет взаимодействовать с голосовыми интерфейсами в ваших веб приложениях. Web Speech API состоит из двух частей: SpeechSynthesis (Текст-в-Речь), и SpeechRecognition (Асинхронное распознавание речи)

+
+ +

Концепции и использование Web Speech

+ +

Web Speech API позволяет веб приложениям управлять голосовыми данными. Существует два компонента к этому API:

+ + + +

Для большей информации по использованию этих фич, смотрите Using the Web Speech API.

+ +

Интерфейсы Web Speech API

+ +

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

+ +
+
{{domxref("SpeechRecognition")}}
+
The controller interface for the recognition service; this also handles the {{domxref("SpeechRecognitionEvent")}} sent from the recognition service.
+
{{domxref("SpeechRecognitionAlternative")}}
+
Представляет одно слово которое было распознано службой распознавания голоса.
+
{{domxref("SpeechRecognitionError")}}
+
Представляет сообщения об ошибках из службы распознавания.
+
{{domxref("SpeechRecognitionEvent")}}
+
The event object for the {{event("result")}} and {{event("nomatch")}} events, and contains all the data associated with an interim or final speech recognition result.
+
{{domxref("SpeechGrammar")}}
+
Слова или шаблоны слов которые мы хотим чтобы служба распознавания распознала.
+
{{domxref("SpeechGrammarList")}}
+
Представляет список объектов {{domxref("SpeechGrammar")}}.
+
{{domxref("SpeechRecognitionResult")}}
+
Представляет одно распознанное совпадение, которое может содержать несколько объектов {{domxref("SpeechRecognitionAlternative")}}.
+
{{domxref("SpeechRecognitionResultList")}}
+
Represents a list of {{domxref("SpeechRecognitionResult")}} objects, or a single one if results are being captured in {{domxref("SpeechRecognition.continuous","continuous")}} mode.
+
+ +

Синтезирование речи

+ +
+
{{domxref("SpeechSynthesis")}}
+
The controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other commands besides.
+
{{domxref("SpeechSynthesisErrorEvent")}}
+
Contains information about any errors that occur while processing {{domxref("SpeechSynthesisUtterance")}} objects in the speech service.
+
{{domxref("SpeechSynthesisEvent")}}
+
Contains information about the current state of {{domxref("SpeechSynthesisUtterance")}} objects that have been processed in the speech service.
+
{{domxref("SpeechSynthesisUtterance")}}
+
Represents a speech request. It contains the content the speech service should read and information about how to read it (e.g. language, pitch and volume.)
+
+ +
+
{{domxref("SpeechSynthesisVoice")}}
+
Represents a voice that the system supports. Every SpeechSynthesisVoice has its own relative speech service including information about language, name and URI.
+
{{domxref("Window.speechSynthesis")}}
+
Specced out as part of a [NoInterfaceObject] interface called SpeechSynthesisGetter, and Implemented by the Window object, the speechSynthesis property provides access to the {{domxref("SpeechSynthesis")}} controller, and therefore the entry point to speech synthesis functionality.
+
+ +

Примеры

+ +

Web Speech API репозиторий на GitHub содержит примеры, показывающие распознавание и синтез речи.

+ +

Спецификации

+ + + + + + + + + + + + + + +
СпецификацияСтатусКомментарий
{{SpecName('Web Speech API')}}{{Spec2('Web Speech API')}}Initial definition
+ +

Browser compatibility

+ +
{{CompatibilityTable}}
+ +
+ + + + + + + + + + + + + + + + + + + + + +
FeatureChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari (WebKit)
Basic support{{CompatChrome(33)}}[1]{{CompatVersionUnknown}}{{CompatGeckoDesktop(49)}}[2]{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChromeEdgeFirefox Mobile (Gecko)Firefox OSIE PhoneOpera MobileSafari Mobile
Basic support{{CompatUnknown}}{{CompatVersionUnknown}}[1]{{CompatVersionUnknown}}{{CompatUnknown}}2.5{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ + + +

Firefox OS permissions

+ +

To use speech recognition in an app, you need to specify the following permissions in your manifest:

+ +
"permissions": {
+  "audio-capture" : {
+    "description" : "Audio capture"
+  },
+  "speech-recognition" : {
+    "description" : "Speech recognition"
+  }
+}
+ +

You also need a privileged app, so you need to include this as well:

+ +
  "type": "privileged"
+ +

Speech synthesis needs no permissions to be set.

+ +

Смотрите также

+ + diff --git a/files/ru/web/api/web_speech_api/using_the_web_speech_api/index.html b/files/ru/web/api/web_speech_api/using_the_web_speech_api/index.html new file mode 100644 index 0000000000..f869af47d3 --- /dev/null +++ b/files/ru/web/api/web_speech_api/using_the_web_speech_api/index.html @@ -0,0 +1,416 @@ +--- +title: Применение Web Speech API +slug: Web/API/Web_Speech_API/Using_the_Web_Speech_API +tags: + - API + - Web Speech API + - Воспроизведение речи + - Распознавание речи + - Синтез речи +translation_of: Web/API/Web_Speech_API/Using_the_Web_Speech_API +--- +

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

+ +

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

+ +

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

+ +

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

+ +
+

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

+
+ +

Демо

+ +

Для запуска демо достаточно перейти по ссылке на приложение или скачать репозиторий, установить зависимости (npm install) и запустить приложение (npm run start), после чего открыть localhost:4001 в браузере.

+ +

+ +

после озвучки команды

+ +

+ +

Браузерная поддержка

+ +

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

+ + + +

Традиционно, самая актуальная информация по поддержке чего-либо в браузерах на caniuse.

+ +

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) - по ссылке можете почитать про это больше.
+ +

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

+ + + +

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

+ +

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

+ +

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

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

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

+ +
speechRecognitionList.addFromString(grammar, 1);
+
+ +

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

+ + + +
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 для этой цели.

+ +

Демо

+ +

То же самое приложение из предыдущего примера.
+ Ccылка на приложение или репозиторий (клонируем, затем npm install && npm run start в терминале, после чего открыть localhost:4001 в браузере).
+
+ Пользовательский интерфейс включает в себя набор элементов для ввода текста, задания высоты тона, скорости воспроизведения и непосредственного выбора голоса, которым будет текст произнесен.

+ +

После ввода текста вы можете нажать Play для запуска.

+ +

+ +

Браузерная поддержка

+ +

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

+ + + + + +

HTML и CSS

+ +

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

+ +

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

+ +
<section>
+  <h1>Синтез речи</h1>
+  <p>Введите текст в поле ниже и нажмите кнопку "Play", чтобы прослушать запись. Выбирайте возможные голоса из списка ниже</p>
+
+  <form>
+    <input type="text" class="text">
+    <div class="row">
+      <div class="values-box">
+        <div class="value-box">
+          <div>Темп (Rate)</div>
+          <div class="value value--rate-value">1</div>
+        </div>
+
+        <div class="value-box">
+          <div>Диапазон (Pitch)</div>
+          <div class="value value--pitch-value">1</div>
+        </div>
+      </div>
+
+      <div class="ranges-box">
+        <input type="range" min="0.5" max="2" value="1" step="0.1" id="rate">
+        <input type="range" min="0" max="2" value="1" step="0.1" id="pitch">
+      </div>
+    </div>
+
+    <select>
+    </select>
+
+    <button id="play" 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(), передавая значение текстового поля в конструктор.

+ +

Затем нам нужно выяснить, какой голос использовать. Мы используем свойство HTMLSelectElement selectedOptions для получения выбранного элемента <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.

+ +
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();
+};
+
+ +

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

+ +

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

+ +
pitch.onchange = function() {
+  pitchValue.textContent = pitch.value;
+};
+
+rate.onchange = function() {
+  rateValue.textContent = rate.value;
+};
+
-- cgit v1.2.3-54-g00ecf