Skip to main content
Glama

FireRedTTS3 — TTS multilingüe (24 idiomas, incl. ucraniano)

Servicio local de síntesis de voz basado en FireRedTTS3 con API HTTP y servidor MCP. El tercero de la serie junto a ukrainian-tts (StyleTTS2, :8000) y HolosTTS (:8010); este — en :8020.

El modelo salió el 13.08.2026, licencia Apache 2.0, pesos públicos.

En qué se diferencia de los vecinos

ukrainian-tts

HolosTTS

firered-tts

Idiomas

ucraniano

ucraniano

24 + 21 dialectos

Voces predefinidas

27

ninguna

Clonación

no

sí (vector de estilo)

sí (zero-shot)

Transcripción de referencia necesaria

no

Diseño de voz por descripción

no

no

(instruct)

Edición de grabación

no

no

(instruct)

Tamaño en memoria

~1 GB

~4 GB

~7.7 GB de pesos, ~13 GB con proceso

Acentos (ucraniano)

diccionario + ByT5

diccionario + ByT5

ninguno

Tres cosas que conviene entender antes de empezar:

1. No hay voces predefinidas. La biblioteca vacía = no hay nada que sintetizar. Primero introduces una voz a partir de cualquier grabación de habla (add_firered_voice), y luego la usas por nombre. El modelo clona zero-shot directamente durante la síntesis.

2. Se necesita la transcripción de la referencia. Al modelo no le basta el audio — necesita también el texto de lo que se oye en él. Si no se la das, la reconocemos con Whisper, pero tu propio texto siempre es más preciso.

3. No hay acentos. Ni diccionario, ni fallback de ByT5, ni acento manual Mu+dro, como en los vecinos. El modelo pone los acentos solo a partir del contexto, y en homógrafos (za'mok/za'mok) los confundirá. Es una limitación fundamental del modelo multilingüe — si los acentos son críticos, HolosTTS sigue siendo la mejor opción para ucraniano puro.

Related MCP server: STT2TTS MCP

Instalación

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

setup.sh hace cuatro cosas:

  1. .venv con Python 3.11, torch 2.8.0 para MPS/CPU

  2. clona el upstream en vendor/FireRedTTS3 en el commit fijado 00570ad

  3. le aplica el parche para Apple Silicon — ver más abajo

  4. descarga los pesos base+redae (~11.4 GB) en pretrained_models/

Los pesos por separado (mejor en modo detached):

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

Para qué sirve el parche

El upstream está escrito exclusivamente para NVIDIA y en Mac no funciona en absoluto:

Lugar

Antes

Después

llm/fireredtts3_base.py:49

attn_implementation: flash_attention_2

sdpa

redae/redae.py:37,122

lo mismo, ×2

sdpa

base.py:143, instruct.py:142, redae.py:470

@torch.autocast(device_type='cuda')

dispositivo dinámico

base.py:267, instruct.py:319

self.device = torch.device('cuda')

desde FIRERED_DEVICE

utils/utils.py:8,9

torch.cuda.manual_seed sin comprobación

bajo if cuda.is_available()

flash_attn — solo CUDA, en Metal no compila en principio; sdpa funciona en todas partes, incluso en NVIDIA, así que el parche no rompe nada.

El décimo cambio está aparte: base.py:317 — no es portabilidad, sino rendimiento (caché de codificación de referencia, ver «Rendimiento» más abajo).

src/patch_upstream.py es idempotente y falla si el reemplazo no ha acertado — si el upstream cambia, te enteras de inmediato, no con un error de CUDA en la primera síntesis.

Ejecución

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

No hace falta ejecutarlo por separado — el servidor MCP levantará el backend solo. El backend se apaga tras 1800s de inactividad (IDLE_SHUTDOWN_SECONDS) y libera memoria.

run.sh toma el lock del puerto (data/.start-<puerto>.lock): un segundo lanzamiento con el servicio vivo simplemente termina con código 0. Es intencionado — el autostart lo invocan varios clientes a la vez, y /health calla durante los ~90s de carga.

API HTTP

Método

Endpoint

Qué hace

GET

/health

estado, dispositivo, qué modelo hay en memoria

GET

/voices

nombres de voces, como en los vecinos (filtros gender, language; full=1 → con metadatos)

GET

/languages

24 idiomas + 21 dialectos

POST

/clone_voice

referencia + transcripción → voz

DELETE

/voices/{name}

eliminar voz (la grabación original no se toca)

POST

/tts

texto → bytes de audio en la respuesta

POST

/synthesize

texto → archivo en DATA_DIR, JSON con la ruta

POST

/voice_design

descripción de voz → audio (instruct)

POST

/edit

edición de grabación: 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

Ver mcp_server/README.md. En resumen:

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

Herramientas: firered_backend_status, list_firered_voices, add_firered_voice, delete_firered_voice, synthesize_firered_speech, design_firered_voice, edit_firered_speech.

Memoria y velocidad

Mac mini M4, 16 GB. En disco base (7.9) + redae (3.5) = 11.4 GB, pero en memoria caben ~7.7 GB: el backbone LLM se carga en fp16 (4.2 en lugar de 8.4 — ver optimización 2 más abajo), el resto permanece en fp32.

Los pesos no son toda la historia. Medido en un proceso vivo tras la síntesis:

phys_footprint:      13 ГБ
phys_footprint_peak: 14 ГБ

La diferencia entre 7.7 y 13 — caché del asignador MPS, caché KV y activaciones de generación. En 16 GB esto va justo incluso con un solo proceso, y ps/RSS aquí miente (muestra décimas de gigabyte: los buffers MPS en memoria unificada no aparecen en RSS). Mide footprint, no ps.

Consecuencias incorporadas en el código:

  • en memoria vive exactamente un modelo — base o instruct; cambiar = recarga completa (minutos, se registra en el log ruidosamente);

  • la síntesis está serializada con un lock global — dos peticiones paralelas en 16 GB dan OOM, no aceleración;

  • run.sh toma el lock del puerto — si no, varios clientes que hacen autostart a la vez levantan una copia del backend cada uno (caso real: siete procesos en 16 GB);

  • autoapagado por inactividad de 1800s — más largo que el de los vecinos a propósito: reiniciar cuesta ~40s de compilación de shaders, así que mantener el proceso vivo sale más rentable;

  • Whisper para la transcripción automática — int8 en CPU, se descarga inmediatamente después del reconocimiento.

Velocidad y cuatro optimizaciones

La ejecución ingenua del upstream en M4 daba ×189 del tiempo real — 3 segundos de ucraniano tardaban 9.5 minutos. Tres correcciones dieron ×4.0, es decir, 48 veces más rápido; la cuarta lo llevó a ×2.7. Qué estaba mal exactamente (medido con tools/profile_steps.py e instrumentación):

1. Autocast en el paso del bucle AR — el mayor problema. El upstream cuelga @torch.autocast como decorador en _backbone_one_step, es decir, la región autocast se abre y se cierra en CADA paso de la autorregresión. La caché de recasteo de pesos en torch vive exactamente dentro de la región, así que 1.7B parámetros fp32 se convertían a half en cada paso. Paso del backbone: 19000 ms → 2710 ms. Ahora autocast está desactivado por defecto, y el casteo se hace explícitamente en el límite del backbone.

2. Backbone en fp32. Los pesos están guardados en float32 (3.0B parámetros = 11.4 GB), lo que en 16 GB significa swap. Convertimos a half solo el backbone LLM (4.2 GB en lugar de 8.4), y redae y el decodificador flow los dejamos en fp32 — el upstream ahí trabaja deliberadamente en precisión completa, y half rompe el matmul de MPS. Paso: 2710 → 1387 ms.

3. Compilación de shaders de Metal. La mayor parte de la «lentitud» resultó ser puntual: Metal compila los kernels en la primera ejecución. Mediciones individuales del paso del backbone: 9873, 2104, 120, 93, 96, 97… ms. Por eso el servicio hace un calentamiento al inicio (FIRERED_WARMUP=1) y tiene un timeout de inactividad largo — reiniciar cuesta ~40 segundos de compilación.

4. Caché de codificación de referencia. generate() se llama en CADA frase, y cada llamada volvía a pasar el codificador redae por la grabación de referencia — 5.58s cada vez, independientemente de la longitud del texto. La clave de la caché es el contenido del audio, no el id del tensor, así que no puede sustituir la voz. En una ejecución de 6.6 min de audio (14 fragmentos): 30 aciertos contra 2 fallos ≈ 150s, es decir, ~11% del tiempo.

Un minuto de audio se calcula en ~2.7 minutos (Mac mini M4 / 16 GB, modelo calentado, caché de referencia caliente; mejor de 5 rondas alternadas sobre 3.0s de ucraniano, la mediana da ×2.9). No hay tiempo real, pero ya es una herramienta de trabajo, no un «déjalo corriendo toda la noche».

Perfil de generación caliente: decodificador flow 57%, backbone 18%, redae 11%.

n_timesteps — pasos de ODE en el decodificador flow, la parte más cara. El parámetro está disponible en /tts, MCP y FIRERED_N_TIMESTEPS, pero el valor por defecto es 10, como en el upstream: el upstream no lo documenta ni propone tocarlo en ningún sitio, y por debajo de 4 la calidad se vuelve notablemente más basta. Según la misma medición: 10 → ×2.7, 6 → ×1.9, 4 → ×1.3, 2 → ×1.0. Bájalo solo para una tarea concreta y verificando de oído.

Normalización de texto

El TN integrado (wetext) solo conoce chino e inglés, así que para ucraniano es inútil y no lo instalamos. 19:30, 250 грн, 2026 р. el modelo lo vocalizará como salga.

Dos salidas:

  1. escribir el texto directamente con palabras;

  2. activar LLM-TN — FIRERED_TN_API_URL / _API_KEY / _MODEL en .env. Sirve cualquier endpoint compatible con OpenAI, incluido el local (llama.cpp / vLLM / Ollama) — entonces todo permanece offline.

Licencia

Código y pesos — Apache 2.0. En el README del upstream se indica por separado que la clonación zero-shot es «solely for academic research purposes» — esto contradice Apache 2.0 y para el uso comercial de voces clonadas mira con cuidado. Para uso doméstico la cuestión no se plantea.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Hosted pay-per-use TTS: 54 neural voices, 9 languages incl. Brazilian Portuguese. $10 free credits.

  • MCP server exposing the AceDataCloud Fish Audio API (text-to-speech with voice conditioning)

  • MCP server for Kling AI video generation

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/taral14/firered-tts'

If you have feedback or need assistance with the MCP directory API, please join our Discord server