Skip to main content
Glama

FireRedTTS3 — многоязычный TTS (24 языка, вкл. украинский)

Локальный сервис синтеза речи на FireRedTTS3 с HTTP-API и MCP-сервером, на порту :8020.

Модель вышла 13.08.2026, лицензия Apache 2.0, веса публичные.

Что стоит знать перед стартом

Пресетных голосов нет. Пустая библиотека = синтезировать нечем. Сначала заводишь голос из любой записи речи (add_firered_voice), дальше используешь его по имени. Модель клонирует zero-shot прямо во время синтеза.

Нужен транскрипт референса. Модели мало самого аудио — нужен ещё текст того, что в нём звучит. Не передашь — распознаем Whisper'ом, но свой текст всегда точнее.

Ударений нет. Ни словаря, ни ByT5-фолбека, ни ручного Му+дрого. Ударения модель ставит сама из контекста и на омографах (за́мок/замо́к) будет путаться. Это принципиальное ограничение многоязычной модели.

Related MCP server: STT2TTS MCP

Установка

cd /Users/admin/Projects/firered-tts
./setup.sh                    # venv + залежності + апстрім + патч + ваги

setup.sh делает четыре вещи: поднимает .venv с Python 3.11 и torch 2.8.0 под MPS/CPU, клонирует апстрим в vendor/FireRedTTS3 на зафиксированном коммите 00570ad, патчит его под Apple Silicon (см. ниже) и тянет веса base+redae (~11.4 ГБ) в pretrained_models/.

Веса отдельно (долго — лучше detached):

nohup ./download-weights.sh base > data/download.log 2>&1 &
./download-weights.sh instruct   # +7.9 ГБ, для дизайну голосу й редагування

Зачем патч

Апстрим написан исключительно под NVIDIA и на Mac не запускается вообще: flash_attn на Metal не собирается в принципе, устройство зашито как cuda, autocast прибит гвоздями к CUDA. Патч заменяет flash_attention_2 на sdpa (работает везде, в т.ч. на NVIDIA), делает устройство динамическим и добавляет оптимизации из раздела о скорости. Полный список — в шапке src/patch_upstream.py.

Патч идемпотентен и падает, если замена не попала — если апстрим изменился, ты узнаешь об этом сразу, а не CUDA-ошибкой на первом синтезе.

Запуск

./run.sh                      # http://localhost:8020

Отдельно запускать не обязательно — MCP-сервер поднимет бекенд сам. Бекенд выключается после простоя и освобождает память.

HTTP API

Метод

Эндпойнт

Что делает

GET

/health

статус, устройство, какая модель в памяти

GET

/voices

имена голосов (фильтры gender, language; full=1 → с метаданными)

GET

/languages

24 языка + 21 диалект

POST

/clone_voice

референс + транскрипт → голос

DELETE

/voices/{name}

удалить голос (оригинал записи не трогается)

POST

/tts

текст → аудио-байты в ответе

POST

/synthesize

текст → файл в DATA_DIR, JSON с путём

POST

/voice_design

описание голоса → аудио (instruct)

POST

/edit

правка записи: semantic | acoustic (instruct)

# 1) завести голос
curl -X POST localhost:8020/clone_voice -H 'Content-Type: application/json' -d '{
  "audio": "prompts/зразок.wav", "name": "Богдан",
  "prompt_text": "Це зразок мого голосу для клонування.",
  "language": "Ukrainian", "gender": "male"}'

# 2) озвучити
curl -X POST localhost:8020/tts -H 'Content-Type: application/json' -d '{
  "text": "Сьогодні чудова погода, ходімо гуляти в парк.",
  "voice": "Богдан", "format": "mp3"}' -o out.mp3

# Або one-shot — без реєстрації голосу: передай reference_audio замість voice,
# транскрипт зробить Whisper (перший виклик +~30с, далі кешується)
curl -X POST localhost:8020/tts -H 'Content-Type: application/json' -d '{
  "text": "Сьогодні чудова погода.", "reference_audio": "prompts/зразок.mp3",
  "format": "mp3"}' -o out.mp3

MCP

См. mcp_server/README.md. Кратко:

claude mcp add firered-tts -- /Users/admin/Projects/firered-tts/.venv/bin/python \
  /Users/admin/Projects/firered-tts/mcp_server/server.py

Инструменты: firered_backend_status, list_firered_voices, add_firered_voice, delete_firered_voice, synthesize_firered_speech, design_firered_voice, edit_firered_speech.

Память

Mac mini M4, 16 ГБ. Веса на диске: base (7.9) + redae (3.5) = 11.4 ГБ. В памяти меньше — LLM-бекбон живёт в half (4.2 вместо 8.4 ГБ), — но на 16 ГБ это всё равно впритык. Последствия, заложенные в код:

  • в памяти живёт ровно одна модель — base или instruct; переключение = полная перезагрузка (минуты, громко логируется);

  • синтез сериализован глобальным локом — два параллельных запроса на 16 ГБ дают OOM, а не ускорение;

  • автоостановка по простою 1800с — долго намеренно: рестарт стоит ~40с компиляции шейдеров, так что держать процесс живым выгоднее;

  • Whisper для автотранскрипта — int8 на CPU, выгружается сразу после распознавания.

Скорость и четыре оптимизации

Наивный запуск апстрима на M4 давал ×186 реального времени — 3 секунды украинского считались 9 минут. После четырёх исправлений стало ×3.0, то есть в ~60 раз быстрее. Что именно было не так (всё замерено tools/profile_steps.py):

1. Autocast на шаге AR-цикла — главная беда. Апстрим вешает @torch.autocast декоратором на _backbone_one_step, то есть регион открывается и закрывается на КАЖДОМ шаге авторегрессии. Кеш перекастов весов в torch живёт ровно внутри региона, так что 1.7B параметров fp32 перегонялись в half на каждом шаге. Шаг бекбона: 19000 → 2710 мс. Теперь autocast выключен, а каст делается явно на границе бекбона.

2. Бекбон в fp32. Веса сохранены в float32 (3.0B параметров), что на 16 ГБ означает своп. Переводим в half только LLM-бекбон (4.2 ГБ вместо 8.4), а redae и flow-декодер оставляем fp32 — half ломает там MPS-matmul. Шаг: 2710 → 1387 мс.

3. Референс кодировался заново на каждое предложение. generate() вызывается на каждое предложение текста, и каждый вызов прогонял redae-энкодер по тому же референсному записи: 5.6с каждый раз, независимо от длины текста. Теперь кеш с ключом по содержимому аудио. На 6.6 мин аудио — 30 попаданий против 2 промахов, ~11% времени прогона.

4. Компиляция Metal-шейдеров. Самая большая часть «медлительности» оказалась разовой: Metal компилирует ядра при первом выполнении. Поштучные замеры шага бекбона: 9873, 2104, 120, 93, 96, 97… мс. Поэтому сервис делает прогрев на старте (FIRERED_WARMUP=1) и имеет долгий таймаут простоя.

Замерено на Mac mini M4 / 16 ГБ, 3.0с украинского, прогретая модель:

n_timesteps

Время

×реального времени

Качество

10 (дефолт)

12 с

×4.0

эталон

6

10 с

×3.0

разница едва слышна

4

7 с

×2.3

заметно грубее

2

6 с

×1.9

заметные артефакты

Профиль прогретой генерации: flow-декодер 57%, бекбон 18%, redae 11% — самый действенный рычаг именно n_timesteps. Real-time нет, но это уже рабочий инструмент, а не «запусти на ночь».

Text normalization

Встроенный TN (wetext) знает только китайский и английский, так что для украинского он бесполезен, и мы его не ставим. 19:30, 250 грн, 2026 р. модель озвучит как получится. Два выхода: писать текст сразу словами, или включить LLM-TN — FIRERED_TN_API_URL / _API_KEY / _MODEL в .env. Годится любой OpenAI-совместимый эндпойнт, включая локальный (llama.cpp / vLLM / Ollama) — тогда всё остаётся офлайн.

Лицензия

Код и веса — Apache 2.0. В README апстрима отдельно написано, что zero-shot клонирование «solely for academic research purposes» — это противоречит Apache 2.0 и на коммерческое использование клонированных голосов смотри осторожно. Для домашнего использования вопрос не стоит.

Related MCP Connectors

Related MCP Servers