Задача: Добавить браузерную озвучку букв, слогов и отдельных слов
Добавить браузерную озвучку букв, слогов и отдельных слов
Использовать Web Speech API для воспроизведения учебных единиц: букв, слогов и отдельных слов.
Цель
Добавить браузерную озвучку учебных единиц без отдельного TTS-бэкенда: букв, слогов и отдельных слов.
Основной сценарий:
- Ребёнок видит букву, слог или слово.
- Нажимает кнопку воспроизведения.
- Браузер произносит соответствующий текст.
На первом этапе использовать встроенный Web Speech API браузера.
Основное API
const utterance = new SpeechSynthesisUtterance('Собака')
utterance.lang = 'ru-RU'
window.speechSynthesis.speak(utterance)
Остановка текущей речи:
window.speechSynthesis.cancel()
Полезные параметры:
utterance.lang = 'ru-RU'
utterance.rate = 1
utterance.pitch = 1
utterance.volume = 1
lang— язык/локаль синтеза;rate— скорость речи;pitch— высота голоса;volume— громкость 0..1;voice— конкретный системный голос.
Выбор русского голоса
const voices = window.speechSynthesis.getVoices()
const russianVoice = voices.find(
voice => voice.lang.toLowerCase().startsWith('ru'),
)
const utterance = new SpeechSynthesisUtterance('Рыба')
utterance.lang = 'ru-RU'
utterance.voice = russianVoice ?? null
window.speechSynthesis.speak(utterance)
Список голосов может загружаться асинхронно:
window.speechSynthesis.onvoiceschanged = () => {
const voices = window.speechSynthesis.getVoices()
console.log(voices)
}
Базовый helper
export type SpeakOptions = {
lang?: string
rate?: number
pitch?: number
volume?: number
voice?: SpeechSynthesisVoice | null
}
export const speak = (
text: string,
options: SpeakOptions = {},
) => {
window.speechSynthesis.cancel()
const utterance = new SpeechSynthesisUtterance(text)
utterance.lang = options.lang ?? 'ru-RU'
utterance.rate = options.rate ?? 1
utterance.pitch = options.pitch ?? 1
utterance.volume = options.volume ?? 1
if (options.voice) {
utterance.voice = options.voice
}
window.speechSynthesis.speak(utterance)
return utterance
}
Примеры:
speak('А')
speak('МА')
speak('Собака')
Рекомендуемый hook для React
import { useCallback, useEffect, useState } from 'react'
export const useSpeechSynthesis = () => {
const [voices, setVoices] = useState<SpeechSynthesisVoice[]>([])
useEffect(() => {
const loadVoices = () => {
setVoices(window.speechSynthesis.getVoices())
}
loadVoices()
window.speechSynthesis.addEventListener('voiceschanged', loadVoices)
return () => {
window.speechSynthesis.removeEventListener('voiceschanged', loadVoices)
}
}, [])
const speak = useCallback((text: string) => {
window.speechSynthesis.cancel()
const utterance = new SpeechSynthesisUtterance(text)
utterance.lang = 'ru-RU'
const russianVoice = voices.find(
voice => voice.lang.toLowerCase().startsWith('ru'),
)
if (russianVoice) {
utterance.voice = russianVoice
}
window.speechSynthesis.speak(utterance)
}, [voices])
const stop = useCallback(() => {
window.speechSynthesis.cancel()
}, [])
return {
voices,
speak,
stop,
}
}
Логика UI
Минимально нужны:
- кнопка
Прослушать; - повторное воспроизведение;
- отмена предыдущей речи перед новым
speak(); - состояние
speaking, если оно понадобится для анимации/disable кнопки; - fallback, если
speechSynthesisнедоступен.
События SpeechSynthesisUtterance, которые можно использовать:
utterance.onstart = () => {}
utterance.onend = () => {}
utterance.onerror = event => {}
Важные ограничения
- качество и набор голосов зависят от браузера/ОС;
- одна и та же строка может звучать по-разному на разных устройствах;
- одиночные буквы могут произноситься не так, как ожидается педагогически — это нужно отдельно проверить на целевых браузерах;
- API подходит для готовой озвучки, но не даёт напрямую PCM/AudioBuffer для анализа;
- не смешивать эту задачу с экспериментами собственного синтезатора речи.
Критерий готовности
Буква, слог или отдельное слово передаются одним методом speak(text), корректно произносятся на русском языке, повторный запуск не наслаивается на предыдущий, ошибки и отсутствие API обрабатываются предсказуемо.
Ворклоги
Прогресс: ограничения и странности браузерного SpeechSynthesis
Проверена встроенная браузерная озвучка на отдельных словах, слогах и буквах. Для целых слов API в ряде случаев работает приемлемо, но на коротких слогах и отдельных буквах проявляются заметные и непредсказуемые ошибки интерпретации текста.
Что звучит нормально
Собака— произносится нормально.Ры— произносится нормально.Свинья— произносится нормально.Пель— неожиданно произносится нормально.
Наблюдаемые сбои
Со— звучит примерно как простоС.Р— звучит скорее какЭ.Ре— тоже звучит примерно какЭ.Свинь— вместо слога начинает читать как названия букв: примерноЭс Вэ Ен Мягкий знак. При этомИиНотдельно не проговариваются ожидаемо, а часть последовательности интерпретируется какЕн.Ковь— тоже разваливается на чтение по буквам.Солн— также читается по буквам/не как слог.Ко— звучит какКа.Ар— звучит какА.Де— звучит какДэ.
Основной вывод
SpeechSynthesisUtterance хорошо подходит для обычных слов и фраз, но не гарантирует корректное произношение искусственно выделенных слогов и отдельных букв.
TTS-движок пытается интерпретировать короткую строку как естественный текст, название буквы, аббревиатуру или неизвестную лексему. Поэтому одинаковая последовательность символов может озвучиваться по-разному в зависимости от длины и контекста.
Особенно проблемны:
- одиночные согласные;
- короткие слоги из 2 букв;
- слоги с
ь; - обрезанные части слова, которые не являются самостоятельными лексемами;
- сочетания, похожие на буквенные сокращения.
Практическое следствие
Нельзя считать браузерный TTS универсальным источником правильного произношения для учебной механики буква → слог → слово.
Для целых слов его можно использовать напрямую, но для букв и слогов потребуется один из вариантов:
- ручные исключения / словарь альтернативных строк для конкретного TTS;
- предварительно записанные аудиофайлы;
- отдельный TTS/SSML-движок с более управляемым произношением;
- гибрид: слова через браузерный TTS, проблемные буквы/слоги — через подготовленное аудио.
Важно
Эти наблюдения относятся к фактическому поведению текущего браузерного/системного голоса. На другой ОС, браузере или другом SpeechSynthesisVoice результат может отличаться, поэтому подобные исключения нельзя считать универсальными для всех устройств.