Я провожу много времени на Medium: иногда пишу, но по большей части читаю. Изучаю опыт разработчиков, которым они делятся с сообществом.
Недавно заметил, что для каждой статьи Medium предлагает кнопку воспроизведения. Сначала подумал, что такая привилегированная функция предоставляется только избранным статьям или авторам. Но оказывается, она доступна всем! Это значит, что на Medium можно слушать материал публикаций.
И, как любой разработчик, я сразу же заинтересовался решением этой задачи. Для такого случая JavaScript предоставляет веб-API под названием Web Speech API. Однако сам я с ним еще не работал.
Поэтому предлагаю совместно познакомиться с этим инструментом и применить его на практике.
Голосовые данные встраиваются в онлайн-приложения с помощью Web Speech API. Мы создадим простую веб-страницу, которая реализует преобразование текста в речь.
Сначала создаем новую директорию и 2 файла: index.html
и text-to-speech.js
.
Файл HTML
Файл HTML
включает следующие элементы.
- Меню
select
без предлагаемых вариантов. С помощью JavaScript пустое менюselect
заполняется списком возможных голосов. - Слайдеры диапазона для громкости, высоты и скорости звука.
textarea
для ввода текста.- Кнопки управления речью.
В демопримере для стилевого оформления кода используется Bootstrap 5. Ниже представлен код:
<html lang="en">
<head>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<title>Text to Speech</title>
<style>
.card {
padding: 1rem 1.5rem;
border-radius: 7px;
box-shadow: rgb(45 46 46 / 35%) 0px 4px 32px 0px, rgb(45 46 46 / 8%) 0px 4px 16px 0px, rgb(45 46 46 / 10%) 0px 0px 4px 0px;
}
</style>
</head>
<body class="container mt-5 bg-light">
<div class="card">
<h2>Convert Text to Speech</h2>
<h5>Listen to those words!</h5>
<p class="lead mt-4">Select Voice</p>
<!-- Select Menu for Voice -->
<select id="voices" class="form-select"></select>
<!-- Range Slliders for Volume, Rate & Pitch -->
<div class="d-flex mt-4">
<div>
<p class="lead">Volume</p>
<input type="range" min="0" max="1" value="1" step="0.1" id="volume" />
<span id="volume-label" class="ms-2">1</span>
</div>
<div class="mx-5">
<p class="lead">Rate</p>
<input type="range" min="0.1" max="10" value="1" id="rate" step="0.1" />
<span id="rate-label" class="ms-2">1</span>
</div>
<div>
<p class="lead">Pitch</p>
<input type="range" min="0" max="1" value="1" step="0.1" id="pitch" />
<span id="pitch-label" class="ms-2">1</span>
</div>
</div>
<!-- Text Area for the User to Type -->
<textarea class="form-control mt-5" cols="30" rows="10" placeholder="Type here..."></textarea>
<!-- Control Buttons -->
<div class="mb-5">
<button id="start" class="btn btn-success mt-5 me-3">Start</button>
<button id="pause" class="btn btn-warning mt-5 me-3">Pause</button>
<button id="resume" class="btn btn-info mt-5 me-3">Resume</button>
<button id="cancel" class="btn btn-danger mt-5 me-3">Cancel</button>
</div>
</div>
</body>
<script src="./text-to-speech.js"></script>
</html>
Так код выглядит в браузере:
Файл JavaScript
В файле JavaScript используются в основном 3 интерфейса: SpeechSynthesis
, window.speechSynthesis
и SpeechSynthesisUtterance
. Кратко рассмотрим каждый из них.
Интерфейс JavaScript SpeechSynthesis
Представляет собой главный интерфейс сервиса синтеза речи, который управляет синтезом или воспроизведением речи на основе текстового ввода. Он применяется для запуска, остановки, паузы и перезапуска речи, а также для доступа к голосам, поддерживаемых устройством.
Интерфейс SpeechSynthesis
предоставляет следующие методы.
speak()
добавляет высказывание (объектSpeechSynthesisUtterance
) в очередь. Оно озвучивается в том случае, если перед ним нет ожидающего высказывания.pause()
приостанавливает текущую речь.resume()
возобновляет приостановленную речь.cancel()
отменяет все ожидающие высказывания или созданные фрагменты речи, которые еще не были воспроизведены.getVoices()
получает список всех голосов, поддерживаемых устройством.
Свойство JavaScript window.speechSynthesis
Метод speak()
вызывается в интерфейсе контроллера синтеза голоса, на который ссылается данное свойство объекта JavaScript window
.
Когда мы дойдем до кода, эти теоретические моменты станут более понятными.
Интерфейс JavaScript SpeechSynthesisUtterance
В SpeechSynthesisUtterance
мы фактически воспроизводим речь или высказывание на основе предлагаемого текста, включая язык, громкость, высоту голоса, скорость речи и т. д. Создав объект для данного интерфейса, мы предоставляем его методу speak()
объекта SpeechSynthesis
для воспроизведения речи.
Интерфейс SpeechSynthesisUtterance
включает 6 настраиваемых свойств.
Language
(язык)
Свойство language
получает и устанавливает язык высказывания. Если оно не задано, то используется значение <html lang=”en”>
. Если же <html lang=”en”>
недоступно, то задействуется предустановленное значение user-agent
.
speech.lang = "en";
Text
(текст)
При озвучивании высказывания свойство text
получает и задает текст для последующего синтеза. Допускается отправка текста в обычном текстовом формате. В рассматриваемом примере свойство text
устанавливается при нажатии кнопки запуска Start
.
Назначаем кнопке слушателя click
. Мы должны извлечь значение text
из textarea
и установить его для данного свойства при нажатии кнопки:
document.querySelector("#start").addEventListener("click", () => {
speech.text = document.querySelector("textarea").value;
});
Volume
(громкость)
Свойство volume
получает и устанавливает громкость высказывания. Это число с плавающей точкой, которое указывает значение volume
и варьируется от наименьшей величины 0 до наибольшей 1. Если свойство не задано, то значение по умолчанию — 1.
Добавляем слушателя input
к слайдеру диапазона громкости и меняем свойство volume
при обновлении значения слайдера. Минимальные, максимальные и предустановленные значения уже указаны в теге HTML.
Далее к слайдеру диапазона добавляем <span>
, который отображает значение volume
на веб-странице:
document.querySelector("#volume").addEventListener("input", () => { // Получение значения volume из input const volume = document.querySelector("#volume").value; // Установка свойства volume экземпляра SpeechSynthesisUtterance speech.volume = volume; // Обновление метки volume document.querySelector("#volume-label").innerHTML = volume; });
Rate
(скорость)
Свойство rate
возвращает и устанавливает скорость высказывания. Это число с плавающей точкой, представляющее значение rate
. Оно варьируется от наименьшей величины 0,1 до наибольшей 10. Если свойство не задано, значение по умолчанию — 1.
Все действия, выполненные для volume
, повторяем применительно к rate
:
document.querySelector("#rate").addEventListener("input", () => { // Получение значения rate из input const rate = document.querySelector("#rate").value; // Установка свойства rate экземпляра SpeechSynthesisUtterance speech.rate = rate; // Обновление метки rate document.querySelector("#rate-label").innerHTML = rate; });
Pitch
(высота звука)
Свойство pitch
возвращает и устанавливает высоту звука высказывания. Значение также представлено в виде числа с плавающей точкой в диапазоне от 0 до 1.
По аналогии с rate
и volume
выполняем те же действия по отношению к pitch
:
document.querySelector("#pitch").addEventListener("input", () => { // Получение значения pitch из input const pitch = document.querySelector("#pitch").value; // Установка свойства pitch экземпляра SpeechSynthesisUtterance speech.pitch = pitch; // Обновление метки pitch document.querySelector("#pitch-label").innerHTML = pitch; });
Voice
(голос)
Свойство voice
извлекает и преобразует голос, предназначенный для произнесения речи. Мы используем один из объектов SpeechSynthesisVoice
. Если он не настроен, то применяется наиболее подходящий предустановленный голос для языковой настройки высказывания.
Мы должны извлечь список имеющихся голосов в объекте window
, чтобы установить голоса высказывания. Они не будут доступны сразу же при загрузке window
. Это асинхронная операция. Как только голоса загружаются, вызывается событие. Мы можем задать функцию, которая будет выполняться в момент загрузки голосов.
window.speechSynthesis.onvoiceschanged = () => {
// По факту загрузки голосов
};
Метод window.speechSynthesis.getVoices()
позволяет получить список голосов. Он возвращает массив доступных объектов SpeechSynthesisVoice
. Сохраним список в глобальном массиве и воспользуемся им для обновления меню select
предлагаемыми голосами:
let voices = []; // global array
window.speechSynthesis.onvoiceschanged = () => {
// Получение списка голосов
voices = window.speechSynthesis.getVoices();
// Первоначальная установка первого голоса в массиве.
speech.voice = voices[0];
// Установка списка выбора голоса (задаем индекс в качестве значения, который в дальнейшем потребуется при обновлении пользователем голоса посредством меню Select)
let voiceSelect = document.querySelector("#voices");
voices.forEach((voice, i) => (voiceSelect.options[i] = new Option(voice.name, i)));
};
В связи с изменением меню голосов мы можем добавить к нему слушателя события change
и обновить голос экземпляра SpeechSynthesisUtterance
. Воспользуемся номером индекса, установленного в качестве значения для каждого варианта, и глобальным массивом голосов, чтобы обновить голос при его изменении пользователем:
document.querySelector("#voices").addEventListener("change", () => {
speech.voice = voices[document.querySelector("#voices").value];
});
Кнопки управления
Как вы помните, файл index.html
содержит кнопки управления, такие как start
(запуск), resume
(возобновление), pause
(пауза) и cancel
(отмена). Приведем их в рабочее состояние с помощью интерфейса SpeechSynthesis
и его методов.
Кнопка Start
При нажатии кнопки start
экземпляр SpeechSynthesisUtterance
передается в window.speechSynthesis.speak()
. Это действие начинает процесс преобразования текста в речь.
Перед вызовом данной функции необходимо установить свойство text
.
Если во время работы одного экземпляра text-to-speech
вы запускаете еще один, то новый будет поставлен в очередь вслед за текущим.
document.querySelector("#start").addEventListener("click", () => {
speech.text = document.querySelector("textarea").value;
window.speechSynthesis.speak(speech);
});
Кнопка Pause
window.speechSynthesis.pause()
приостанавливает текущее выполнение экземпляра SpeechSynthesisUtterance
:
document.querySelector("#pause").addEventListener("click", () => {
window.speechSynthesis.pause();
});
Кнопка Resume
window.speechSynthesis.resume()
возобновляет работу приостановленного текущего экземпляра SpeechSynthesisUtterance
:
document.querySelector("#resume").addEventListener("click", () => {
window.speechSynthesis.resume();
});
Кнопка Cancel
window.speechSynthesis.cancel()
отменяет выполнение текущего экземпляра SpeechSynthesisUtterance
:
document.querySelector("#cancel").addEventListener("click", () => {
window.speechSynthesis.cancel();
});
Все кнопки управления готовы, и необходимые свойства установлены. Ниже представлен окончательный вариант text-to-speech.js
:
// Инициализация нового объекта SpeechSynthesisUtterance
let speech = new SpeechSynthesisUtterance();
// Установка языка речи
speech.lang = "en";
let voices = []; // глобальный массив доступных голосов
window.speechSynthesis.onvoiceschanged = () => {
// Получение списка голосов
voices = window.speechSynthesis.getVoices();
// Первоначальная установка первого голоса в массиве
speech.voice = voices[0];
// Установка списка выбора голосов (задаем индекс в качестве значения, который в дальнейшем потребуется при обновлении пользователем голоса посредством меню Select)
let voiceSelect = document.querySelector("#voices");
voices.forEach((voice, i) => (voiceSelect.options[i] = new Option(voice.name, i)));
};
document.querySelector("#rate").addEventListener("input", () => {
// Получение значения rate из input
const rate = document.querySelector("#rate").value;
// Установка свойства rate экземпляра SpeechSynthesisUtterance
speech.rate = rate;
// Обновление метки rate
document.querySelector("#rate-label").innerHTML = rate;
});
document.querySelector("#volume").addEventListener("input", () => {
// Получение значения volume из input
const volume = document.querySelector("#volume").value;
// Установка свойства volume экземпляра SpeechSynthesisUtterance
speech.volume = volume;
// Обновление метки volume
document.querySelector("#volume-label").innerHTML = volume;
});
document.querySelector("#pitch").addEventListener("input", () => {
// Получение значения pitch из input
const pitch = document.querySelector("#pitch").value;
// Установка свойства pitch экземпляра SpeechSynthesisUtterance
speech.pitch = pitch;
// Обновление метки pitch
document.querySelector("#pitch-label").innerHTML = pitch;
});
document.querySelector("#voices").addEventListener("change", () => {
// При изменении голоса используется значение меню выбора (которое является индексом голоса в глобальном массиве голосов)
speech.voice = voices[document.querySelector("#voices").value];
});
document.querySelector("#start").addEventListener("click", () => {
// Установка свойства text со значением textarea
speech.text = document.querySelector("textarea").value;
// Запуск озвучки
window.speechSynthesis.speak(speech);
});
document.querySelector("#pause").addEventListener("click", () => {
// Приостановка экземпляра speechSynthesis
window.speechSynthesis.pause();
});
document.querySelector("#resume").addEventListener("click", () => {
// Возобновление приостановленного экземпляра speechSynthesis
window.speechSynthesis.resume();
});
document.querySelector("#cancel").addEventListener("click", () => {
// Отмена экземпляра speechSynthesis
window.speechSynthesis.cancel();
});
Полученный результат на экране браузера:
Пользователь просто вводит текст в textarea
, нажимает на кнопку Start
и его прослушивает.
Читайте также:
- Как создать простую функцию AWS Lambda с помощью TypeScript
- JavaScript 101: метод массива Reduce
- Введение в Webpack для новичков
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Gourav Kajal: Convert Text to Speech Using Web Speech API in JavaScript