Озвучка текста в JavaScript и Node.js
В JavaScript синтез речи встроен: это Web Speech API в браузере. Он бесплатен и не требует настройки, но голоса зависят от системы посетителя, а результат нельзя сохранить в файл. Когда нужен один и тот же естественный голос везде, голоса персонажей или аудиофайлы, нужен движок синтеза.
В этом руководстве — честное сравнение двух путей и вызов бесплатного движка SuperClonica из Node.js и из веб-приложения через локальный HTTP-сервер.
Два способа говорить из JavaScript
Для простой кнопки «прочитать вслух» хватит Web Speech API; для голоса продукта нужен движок.
- Web Speech API: одна строка в браузере, speechSynthesis.speak(new SpeechSynthesisUtterance("Hello!")), с голосами операционной системы или браузера.
- Его голоса различаются между Windows, macOS, Android и браузерами, часть из них — онлайн-сервисы, а звук нельзя сохранить в файл.
- SuperClonica: локальный сервер с одним и тем же естественным голосом на любом устройстве, голосами персонажей и своими голосами и файлами WAV, которые можно хранить и кешировать.
- Он говорит на 31 языке; китайский пока не поддерживается.
Послушайте голоса движка бесплатно онлайн
Прежде чем писать код, откройте страницу любого голоса, впишите фразу от 30 до 100 символов, выберите язык и нажмите «Озвучить». Через несколько секунд вы услышите голос, который может быть у вашего приложения, без регистрации.
Запуск локального сервера речи
Видеокарта NVIDIA ускоряет работу с образом cuda, но не обязательна.
- Запустите сервер на любом процессоре: docker run -d -p 8000:8000 -v superclonica-models:/models superclonica/superclonica:cpu.
- Первый запуск скачивает модель Supertonic 3, около 385 МБ, в том; GET /health покажет, когда сервер готов.
- POST /synthesize принимает JSON с полями text, voice, lang, seed и normalize и отвечает 16-битным моно-WAV.
- voice — стандартное имя от M1 до M5 и от F1 до F5 или разобранное содержимое файла голоса.
Вызов из Node.js и браузера
В Node.js 18 и новее fetch встроен, поэтому при подключённом fs запрос занимает несколько строк: const voice = JSON.parse(fs.readFileSync("voice.json", "utf8")); const res = await fetch("http://localhost:8000/synthesize", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text: "Привет из Node!", voice, lang: "ru", seed: 7 }) }); fs.writeFileSync("hello.wav", Buffer.from(await res.arrayBuffer())); В веб-приложении держите сервер речи закрытым и вызывайте его из своего бэкенда; страница получает звук как blob и проигрывает его через new Audio(URL.createObjectURL(blob)).play(). Тот же текст, голос и seed всегда дают тот же файл, поэтому кешируйте аудио для повторяющихся фраз.
Привычки для продакшена
Не открывайте порт 8000 в интернет как есть: задайте SUPERCLONICA_API_KEY и передавайте его как Bearer-токен, поставьте сервер за обратный прокси с HTTPS или держите его в частной сети. Если запросов много одновременно, запустите больше копий модели через SUPERCLONICA_LANES и замерьте на своём железе: в наших тестах короткая фраза занимала 0,12 с на RTX 5070 Ti и 0,43 с на четырёх потоках процессора.