Pocket TTS en castellano: una voz que funciona en CPU
Afinamos Pocket TTS de Kyutai para el español de España. Funciona en una CPU normal, con muestras en español, inglés, francés y alemán.
Necesitábamos una voz para locuciones, vídeos de demo y recorridos por el producto, en inglés y en español. No queríamos alquilar una GPU para eso: una locución son unos minutos de audio, y una GPU parada entre dos locuciones es justo el tipo de desperdicio del que hablamos en otros artículos de esta web. Así que elegimos Pocket TTS de Kyutai, un modelo de texto a voz pensado para funcionar en CPU, y afinamos su modelo español para que hable el español de España.
Los pesos están en Hugging Face: inferencekey/pocket-tts-spanish-24l-castilian.
Por qué Pocket TTS
- Funciona en CPU. Sin CUDA, sin ROCm, sin GPU. Se instala con
pipy una build de PyTorch para CPU. - Es bastante rápido. El modelo inglés lee unas tres veces más rápido que el tiempo real en una CPU de sobremesa de ocho núcleos (cifras más abajo).
- Habla varios idiomas. Kyutai publica modelos para inglés, español, francés, alemán, italiano, portugués y neerlandés, cada uno en una versión pequeña de 6 capas y otra más grande de 24.
- Clona una voz a partir de un clip corto. Usamos la misma voz (alba) en todos los idiomas.
- Trae un servidor sencillo.
pocket-tts servemantiene el modelo en memoria y responde por HTTP, así que tenemos un pequeño pool de servidores y mandamos una frase a cada uno.
El problema: español con acento extranjero
En inglés suena natural desde el primer momento. En español se entendía, pero no sonaba a España: lee con acento extranjero y pronuncia la "z" y la "c" suave como una "s" (el seseo del español de América). Para alguien de España es lo primero que se nota.
Así que afinamos el modelo español de 24 capas (spanish_24l, unos 316 millones de parámetros en la parte que genera la voz) con unos 2.000 clips de español de España, en una GPU AMD con ROCm.
Lo que aprendimos del entrenamiento:
- Menos pasos fue mejor. La pérdida de validación llegó a su mínimo en el paso 600 (0,4951) y luego volvió a subir, hasta 0,5095 en el paso 1500. En el paso 1500 el modelo había visto los datos unas 47 veces y empezaba a comerse o inventarse palabras: el ASR solo encontró frases completas en 3 de 6 clips de prueba. El paso 600 acertó las 6, igual que el modelo base.
- Publicamos los pesos EMA del paso 600. EMA es una media móvil de los pesos durante el entrenamiento. Cambia el modelo menos que los pesos sin promediar, y eso era lo que buscábamos: conservar todo lo que el modelo base hace bien y corregir el acento.
- Un ASR no basta para juzgar el acento. Qwen3-ASR escribe igual "caza" y "casa", así que te dice si faltan palabras, no cómo suenan. Comprobamos cada muestra con el ASR para ver si faltaban palabras y de oído para el acento.
Escucha
Todas las muestras usan la misma voz (alba), sin editar, generadas en CPU. Todos los clips pasaron una comprobación con el ASR para ver si faltaban palabras.
Español: modelo base frente a nuestro fine-tune
"¿Sabías que el tren de las siete y cuarto sale hoy con veinte minutos de retraso?"
- Modelo base spanish_24l
- Nuestro fine-tune
"La panadería de la esquina abre a las ocho y hace el mejor pan de centeno del barrio."
- Modelo base spanish_24l
- Nuestro fine-tune
Inglés
- "Did you know the seven fifteen train is running twenty minutes late today?"
- "This voice runs on a regular CPU, with no graphics card at all, faster than real time."
Francés
- "Tu savais que le train de sept heures et quart a vingt minutes de retard aujourd'hui ?"
- "La boulangerie du coin ouvre à huit heures et fait le meilleur pain de seigle du quartier."
Alemán
- "Wusstest du, dass der Zug um Viertel nach sieben heute zwanzig Minuten Verspätung hat?"
- "Die Bäckerei an der Ecke öffnet um acht und backt das beste Roggenbrot im Viertel."
Inglés, francés y alemán usan los modelos de 6 capas de Kyutai. El español usa nuestro fine-tune. Con esos cuatro cubrimos lo que necesitamos: inglés y español para nuestros vídeos, y francés y alemán para los otros idiomas de esta web.
Un consejo de la prueba en francés: a veces el modelo lee mal las horas. "Sept heures et quart" salió mal en dos de tres intentos, y el ASR lo detectó. Si una frase importa, compruébala y vuelve a generarla.
Cómo de rápido va en CPU
Medido en nuestra máquina de desarrollo, una VM compartida en un Ryzen 7 5700X (8 núcleos), con 3 instancias del servidor de 2 hilos cada una y seis frases cotidianas por modelo:
| Modelo | Audio | Tiempo de generación | Velocidad |
|---|---|---|---|
| Inglés (6 capas) | 18,4 s | 5,9 s | 3,1x tiempo real |
Español spanish_24l, base (24 capas) | 22,9 s | 19,5 s | 1,2x tiempo real |
| Español, nuestro fine-tune (24 capas) | 22,5 s | 21,5 s | 1,05x tiempo real |
El fine-tune cuesta lo mismo que el modelo base de 24 capas: misma arquitectura, distintos pesos. Los modelos de 24 capas son unas tres veces más lentos que los de 6, así que en CPU sirven para locuciones, no para audiolibros largos. Cada instancia del modelo de 24 capas ocupa unos 2,1 GB de RAM.
Úsalo
Instala Pocket TTS y apúntalo a nuestra configuración en Hugging Face:
pip install pocket-tts
pocket-tts generate \
--config hf://inferencekey/pocket-tts-spanish-24l-castilian/config.yaml \
--text "¿Sabías que el tren de las siete y cuarto sale hoy con veinte minutos de retraso?" \
--output-path tren.wav
Sin --voice usa alba. Para tenerlo en memoria y llamarlo por HTTP:
pocket-tts serve --config hf://inferencekey/pocket-tts-spanish-24l-castilian/config.yaml
Dos cosas que mejoraron nuestras locuciones en español:
- Manda frases enteras, o párrafos cortos enteros. Cada trozo que mandas termina con su propia entonación de cierre, así que partir un párrafo en muchos trozos pequeños lo hace sonar entrecortado.
- Escribe los números con letra. "Siete y cuarto" se lee bien siempre; "7:15" no siempre.
La ficha del modelo en Hugging Face tiene el ejemplo en Python y más muestras (base frente a fine-tune).