Web Speech API имеет две функции: синтез речи, иначе известный как преобразование текста в речь, и распознавание речи. С помощью SpeechSynthesis API мы можем дать команду браузеру прочитать любой текст разными голосами.

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

Что вам понадобится

Если вы хотите создать это приложение, как мы узнали об SpeechSynthesis API, вам понадобится пара вещей:

Когда вы будете готовы, создайте каталог для работы и загрузите в него этот HTML-файл и этот CSS-файл. Убедитесь, что они находятся в одной папке, а файл CSS имеет имя style.css. Откройте HTML-файл в браузере, и вы должны увидеть это:

Давайте начнем с API, заставив браузер впервые поговорить с нами.

API синтеза речи

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

speechSynthesis.speak(new SpeechSynthesisUtterance("Hello, this is your browser speaking."));

Ваш браузер произнесет текст «Здравствуйте, это ваш браузер.» своим голосом по умолчанию. Хотя мы можем немного разбить это.

Мы создали SpeechSynthesisUtterance, который содержал текст, который мы хотели озвучить. Затем мы передали высказывание методу speak объекта speechSynthesis. Это ставит в очередь произнесенное высказывание, а затем запускает говорящий браузер. Если вы отправите в метод speak более одного высказывания, они будут произноситься одно за другим.

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

Синтез речи в веб-приложении

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

Между тегами <script> в нижней части HTML-кода мы начнем с прослушивания события DOMContentLoaded, а затем выберем несколько ссылок на элементы, которые нам понадобятся.

<script>
  window.addEventListener('DOMContentLoaded', () => {
    const form = document.getElementById('voice-form');
    const input = document.getElementById('speech');
  });
</script>

Затем нам нужно прослушать событие отправки в форме и, когда оно сработает, захватить текст из ввода. С этим текстом мы создадим SpeechSynthesisUtterance, а затем передадим его speechSynthesis.speak. Наконец, мы очищаем поле ввода и ждем следующего слова.

<script>
  window.addEventListener('DOMContentLoaded', () => {
    const form = document.getElementById('voice-form');
    const input = document.getElementById('speech');

    form.addEventListener('submit', event => {
      event.preventDefault();
      const toSay = input.value.trim();
      const utterance = new SpeechSynthesisUtterance(toSay);
      speechSynthesis.speak(utterance);
      input.value = '';
    });
  });
</script>

Откройте HTML-код в браузере и введите текст в поле ввода. На этом этапе вы можете игнорировать поле <select>, мы воспользуемся им в следующем разделе. Нажмите «Say it» и слушайте, как браузер зачитывает ваши слова.

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

Выбор голосов для преобразования текста в речь

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

<script>
  window.addEventListener('DOMContentLoaded', () => {
    const form = document.getElementById('voice-form');
    const input = document.getElementById('speech');
    const voiceSelect = document.getElementById('voices');
    let voices;
    let currentVoice;

    form.addEventListener('submit', event => { //... })
  });
</script>

Далее нам нужно заполнить элемент выбора доступными голосами. Для этого мы создадим новую функцию, так как мы можем вызывать ее несколько раз (подробнее об этом чуть позже). Мы можем вызвать speechSynthesis.getVoices(), чтобы вернуть имеющиеся SpeechSynthesisVoice объектов.

Пока мы заполняем параметры голоса, мы также должны определять текущий выбранный голос. Если мы уже выбрали голос, мы можем проверить его по нашему объекту currentVoice, а если мы еще не выбрали голос, мы можем определить голос по умолчанию с помощью свойства voice.default.

    let voices;
    let currentVoice;

    const populateVoices = () => {
      const availableVoices = speechSynthesis.getVoices();
      voiceSelect.innerHTML = '';

      availableVoices.forEach(voice => {
        const option = document.createElement('option');
        let optionText = `${voice.name} (${voice.lang})`;
        if (voice.default) {
          optionText += ' [default]';
          if (typeof currentVoice === 'undefined') {
            currentVoice = voice;
            option.selected = true;
          }
        }
        if (currentVoice === voice) {
          option.selected = true;
        }
        option.textContent = optionText;
        voiceSelect.appendChild(option);
      });
      voices = availableVoices;
    };

    form.addEventListener('submit', event => { //... })

Мы можем сразу позвонить populateVoice. Некоторые браузеры загружают страницу голосов и сразу же возвращают свой список. Другим браузерам необходимо загружать свой список голосов асинхронно, и после загрузки они будут генерировать событие voiceschanged. Однако некоторые браузеры вообще не генерируют это событие.

Чтобы учесть все возможные сценарии, мы немедленно вызовем populateVoices, а также установим его как обратный вызов для события voiceschanged.

      voices = availableVoices;
    };

    populateVoices();
    speechSynthesis.onvoiceschanged = populateVoices;

    form.addEventListener('submit', event => { //... })
  });
</script>

Перезагрузите страницу, и вы увидите элемент <select>, заполненный всеми доступными голосами, включая язык, который поддерживает голос. Однако мы еще не подключили выбор и использование голоса, это будет дальше.

Слушайте событие «изменения» элемента select и всякий раз, когда оно запускается, выбирайте currentVoice, используя selectedIndex элемента <select>.

    populateVoices();
    speechSynthesis.onvoiceschanged = populateVoices;

    voiceSelect.addEventListener('change', event => {
      const selectedIndex = event.target.selectedIndex;
      currentVoice = voices[selectedIndex];
    });

    form.addEventListener('submit', event => { //... })
  });

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

    form.addEventListener('submit', event => {
      event.preventDefault();
      const toSay = input.value.trim();
      const utterance = new SpeechSynthesisUtterance(toSay);
      utterance.voice = currentVoice;
      speechSynthesis.speak(utterance);
      input.value = '';
    });
  });
</script>

Перезагрузите страницу и поиграйте, выбирая разные голоса и говоря разные вещи.

Бонус: построить визуальный индикатор речи

Мы создали синтезатор речи, который может использовать разные голоса, но я хотел добавить еще одну вещь для развлечения. Речевые высказывания генерируют ряд событий, которые вы можете использовать, чтобы ваше приложение реагировало на речь. Чтобы закончить это маленькое приложение, мы сделаем анимационное шоу, когда браузер говорит. Я уже добавил CSS для анимации, поэтому для его активации нам нужно добавить говорящий класс к элементу <main>, когда браузер говорит.

Возьмите ссылку на элемент <main> в верхней части скрипта:

<script>
  window.addEventListener('DOMContentLoaded', () => {
    const form = document.getElementById('voice-form');
    const input = document.getElementById('speech');
    const voiceSelect = document.getElementById('voices');
    let voices;
    let currentVoice;
    const main = document.getElementsByTagName('main')[0];

Теперь мы можем прослушивать начальные и конечные события высказывания, чтобы добавить или удалить класс говорящего. Но если мы удалим класс в середине анимации, он не исчезнет плавно, поэтому мы должны прослушать конец итерации анимации, используя событие animationiteration, а затем удалить класс.

    form.addEventListener('submit', event => {
      event.preventDefault();
      const toSay = input.value.trim();
      const utterance = new SpeechSynthesisUtterance(toSay);
      utterance.voice = currentVoice;
      utterance.addEventListener('start', () => {
        main.classList.add('speaking');
      });
      utterance.addEventListener('end', () => {
        main.addEventListener(
          'animationiteration',
          () => main.classList.remove('speaking'),
          { once: true }
        );
      });
      speechSynthesis.speak(utterance);
      input.value = '';
    });
  });
</script>

Теперь, когда вы запускаете браузер, фон будет мигать синим, а когда произнесение закончится, оно прекратится.

Ваш браузер болтает

В этом посте вы увидели, как начать работу с Speech Synthesis API из Web Speech API. Весь код этого приложения можно найти на GitHub, и вы можете увидеть его в действии или сделать ремикс на Glitch.

Я в восторге от возможностей этого API для создания собственных браузерных ботов, так что ждите новых возможностей в будущем.

Вы использовали API синтеза речи или у вас есть какие-либо планы? Я хотел бы услышать это в комментариях ниже или написать мне на [email protected] или в Twitter на @philnash.

Первоначально опубликовано на https://www.twilio.com.