Clonar voces con F5-TTS en Linux: cuando 15 segundos de muestra son suficientes


28 de abril de 2026

Hace una semana descubrí que para clonar la voz de alguien con calidad de "no se nota que es IA" no necesitas pagar a ElevenLabs ni montar una infraestructura de cluster GPU. Necesitas un audio de WhatsApp de 15 segundos, una RTX modesta y un domingo por la tarde. Y software libre.

Lo que empezó como un "voy a probar a clonar mi propia voz para Ambrosio" terminó con audios mandados al Telegram con la voz de mi mujer dictándome la lista de tareas de casa, y la de un amigo respondiéndose a sí mismo en grupo. El resultado: nadie ha sabido distinguir el audio real del clonado en una primera escucha.

Este post es la receta completa: qué herramientas necesitas, cómo seleccionar una buena muestra, cómo procesarla, y los detalles que separan una clonación plana de una que asusta.

Por qué F5-TTS y no otra cosa

Antes de meternos en barro, contexto. El paisaje de TTS en abril de 2026 está dominado por:

Si lo que quieres es clonar una voz concreta sin mandar el audio a un servidor que no controlas, F5-TTS es ahora mismo la mejor opción libre. Es lo que vamos a montar.

Lo que F5-TTS hace bien

Lo que F5-TTS hace mal

El stack completo

La cadena de herramientas que monté en NixOS:

Herramienta Función
F5-TTS El motor de clonación zero-shot
ffmpeg Convertir audios al formato que F5 quiere
whisper.cpp=| Transcribir muestras automáticamente | | =ffprobe Inspeccionar duraciones, formatos, codecs
PipeWire Capturar audio del sistema en directo
paplay Reproducir resultados
uv (Python) Gestor de venv y deps

Todo libre, todo local. Lo único de pago aquí podría ser la electricidad y la GPU.

Hardware necesario

He probado en una RTX 2060 con 6GB de VRAM. Funciona sin problemas para muestras de hasta 20 segundos y textos de hasta unos 2000 caracteres. Cualquier GPU NVIDIA con 4GB o más debería ir.

Sin GPU, olvídate. Pasa a Kokoro o Piper.

Instalación

F5-TTS se instala con pip en un venv. Yo lo dejé fuera del flake de NixOS para no atarme las manos con el sistema de paquetes. Lo encapsulé en un script bash que hace el setup automático la primera vez.

El proceso de instalación:

# 1. Venv con Python 3.11
uv venv --python 3.11 ~/f5-tts/venv

# 2. F5-TTS (arrastra torch, transformers, etc — son ~5 GB)
VIRTUAL_ENV=~/f5-tts/venv uv pip install f5-tts

# 3. Modelo en español (~1.3 GB de checkpoint + vocab)
~/f5-tts/venv/bin/python3 -c "
from huggingface_hub import hf_hub_download
hf_hub_download(repo_id='jpgallegoar/F5-Spanish',
                filename='model_1200000.safetensors',
                local_dir='/home/user/f5-tts/es-model')
hf_hub_download(repo_id='jpgallegoar/F5-Spanish',
                filename='vocab.txt',
                local_dir='/home/user/f5-tts/es-model')
"

Espacio total en disco: unos 7 GB la primera vez. Tiempo: 5 a 15 minutos según tu conexión.

Whisper para transcripciones

Si vas a clonar voces necesitas transcribir las muestras (lo veremos en un momento). Para eso uso whisper.cpp con el modelo small en español. En NixOS:

environment.systemPackages = [ pkgs.whisper-cpp ];

Y descargas el modelo:

mkdir -p ~/.local/share/whisper/models
curl -L -o ~/.local/share/whisper/models/ggml-small.bin \
  https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin

Cómo funciona F5-TTS por dentro

Antes de la receta, dos minutos de teoría que ahorran muchos intentos fallidos.

F5-TTS es un modelo basado en flow matching. Le das dos cosas:

  1. Audio de referencia (ref_audio): una muestra de la voz que quieres clonar.
  2. Texto de referencia (ref_text): la transcripción EXACTA de ese audio.

A partir de ahí, le pides un texto nuevo (gen_text) y genera audio que suena como la persona del ref_audio leyendo ese gen_text.

La clave que cuesta entender al principio: el ref_text no es un parámetro opcional. Es la herramienta que el modelo usa para alinear los fonemas de la muestra con el espacio de embeddings. Si la transcripción no coincide con el audio palabra por palabra, la clonación pierde calidad rápido.

Esto explica un comportamiento que te volverá loco si no lo sabes: si transcribes "hola que tal" y en el audio dice "hola qué tal", el modelo se desorienta. Yo aprendí esto a base de hostias.

La regla de oro: 12 a 15 segundos

La duración de la muestra es probablemente la decisión más importante de todo el proceso. Después de probar de todo, esta es la tabla:

Duración Resultado
Menos de 8s Voz plana, robótica, sin entonación
8 a 10s Aceptable pero pierde matices
12 a 15s Óptimo: timbre + prosodia + naturalidad
15 a 18s Bien, pero F5 puede empezar a truncar internamente
Más de 18s F5 trunca o degrada. Cortar.

Pero hay un detalle más importante que la duración: el rango prosódico de la muestra. Una frase de 12 segundos con declarativa, énfasis, pausa y pregunta vale infinitamente más que un monólogo plano de 20 segundos.

La mejor muestra que conseguí tenía 11 segundos y contenía:

Resultado: la clonación capturó el carácter de la persona, no solo el timbre.

El flujo completo, paso a paso

Lo que sigue es la receta que llevo aplicando con éxito a varias voces. Asumo que ya tienes una muestra (puede ser un guasap descargado, un fragmento de YouTube, una grabación tuya).

Paso 1: inspeccionar la muestra

Lo primero, ver qué tienes entre manos.

ffprobe -hide_banner /tmp/sample.ogg 2>&1 | grep -E "Duration|Stream"

Si dura menos de 8 segundos, descártala o pide otra. Si dura más de 30, prepárate para recortarla.

Paso 2: convertir a WAV completo (intermedio)

F5-TTS quiere el audio como WAV mono a 16 kHz, 16 bits PCM. Aunque luego vas a recortar un fragmento, conviene primero convertir el audio entero al formato bueno.

ffmpeg -y -i /tmp/sample.ogg \
  -ac 1 -ar 16000 -sample_fmt s16 \
  /tmp/full.wav

Paso 3: transcribir con timestamps

Aquí es donde Whisper se vuelve imprescindible. Necesitamos no solo qué dice la muestra, sino cuándo lo dice, para poder elegir el mejor fragmento.

whisper-cli -m ~/.local/share/whisper/models/ggml-small.bin \
  -f /tmp/full.wav -l es -t 16

Esto te da algo como:

[00:00:00.000 --> 00:00:04.180]   Voy a echar más fotos ahí en el espejo, pero es que claro la gente entra
[00:00:04.180 --> 00:00:08.300]   con la puerta y que me da, entonces me asusto yo, asusto a la gente
[00:00:08.300 --> 00:00:12.620]   y ya no me echan más fotos
[00:00:12.620 --> 00:00:17.820]   escúchame, hay huevos y te va a subir a comer

Con esto delante puedes identificar tramos limpios y elegir el mejor.

Paso 4: elegir un buen fragmento

Esta es la decisión clave. Yo aplico tres reglas:

  1. Duración entre 12 y 15 segundos. Si tienes 11 o 16, no pasa nada, pero apunta a 13.
  2. Variedad prosódica. Busca un tramo con cambios de tono. Una afirmación seguida de una pregunta es oro. Un monólogo monocorde es plomo.
  3. Sin ruido ni solapamiento. Si hay música de fondo, F5 intentará reproducirla. Si hay otra voz interrumpiendo, la mezclará con la tuya.

Marca el fragmento por timestamps. En el ejemplo de arriba podría ser 04.18 a 17.82.

Paso 5: cortar el fragmento

mkdir -p ~/dotfiles/data/tts-voices/menganita

ffmpeg -y -i /tmp/full.wav -ss 4.18 -to 17.82 \
  -ac 1 -ar 16000 -sample_fmt s16 \
  ~/dotfiles/data/tts-voices/menganita/audio.wav

Ahora tienes un audio.wav de unos 13 segundos en el formato exacto que F5 quiere.

Paso 6: escribir el text.txt EXACTO

Esto es lo que más se le suele pasar a la gente. La transcripción tiene que ser palabra por palabra, signo por signo, lo que dice exactamente el audio del paso 5.

cat > ~/dotfiles/data/tts-voices/menganita/text.txt <<'EOF'
con la puerta y que me da, entonces me asusto yo, asusto a la gente y ya no me echan más fotos. Escúchame, hay huevos y te va a subir a comer.
EOF

Copia tal cual del transcript de Whisper, corrigiendo solo errores obvios del transcriptor (no del hablante). Si el hablante dice "asusto a la jente" con seseo, transcribe "asusto a la gente" igualmente: F5 funciona con ortografía estándar, no con transcripción fonética.

Paso 7: probar

~/f5-tts/venv/bin/f5-tts_infer-cli \
  --model F5TTS_Base \
  --ckpt_file ~/f5-tts/es-model/model_1200000.safetensors \
  --vocab_file ~/f5-tts/es-model/vocab.txt \
  --ref_audio ~/dotfiles/data/tts-voices/menganita/audio.wav \
  --ref_text "$(cat ~/dotfiles/data/tts-voices/menganita/text.txt)" \
  --gen_text "Hola, soy menganita hablando desde el ordenador. ¿Te suena raro? A mí también." \
  --device cuda \
  --output_dir /tmp \
  --output_file menganita_prueba.wav

paplay /tmp/menganita_prueba.wav

Tiempo de generación en RTX 2060: unos 8 a 12 segundos para una frase corta. La primera vez carga el modelo y tarda más (60 a 90 segundos).

Si suena plana, vuelve al paso 4 y elige otro fragmento más expresivo. Si suena distorsionada, comprueba que el text.txt coincide con lo que dice el audio.

Un wrapper para no escribir tanto

Tener que recordar la línea anterior cada vez es absurdo. Lo encapsulé en un script f5-say que acepta:

f5-say menganita "lo que sea"
echo "lo que sea" | f5-say menganita -
f5-say -o salida.wav menganita "..."   # a fichero, no reproduce
f5-say -l                              # lista voces disponibles

El script vive en ~/dotfiles/scripts/f5-say, hace auto-instalación si falta el venv o el modelo, y carga las librerías de FFmpeg 4 que F5-TTS exige (en NixOS las librerías nuevas dan problemas con torchaudio).

Bonus 1: capturar voces al vuelo en una reunión

Aquí es donde la cosa se pone interesante. Si estás en un Meet o Zoom y quieres clonar la voz de alguien que está hablando, no necesitas pedirle un audio. Puedes grabar el monitor del sink de PipeWire (lo que sale por tus altavoces).

Mi script capture-talker:

#!/usr/bin/env bash
set -euo pipefail

NAME="${1:-talker}"
SECS="${2:-15}"

# Sink activo (RUNNING, lo que ahora mismo está sonando)
MONITOR=$(pactl list short sources \
          | awk '$NF=="RUNNING" && /monitor/ {print $2; exit}')

OUT="/tmp/${NAME}_$(date +%H%M%S).wav"

ffmpeg -hide_banner -loglevel error \
  -f pulse -i "$MONITOR" \
  -ac 1 -ar 16000 -sample_fmt s16 \
  -t "$SECS" "$OUT"

echo "$OUT"

Uso:

capture-talker             # 15 segundos del monitor activo
capture-talker fulano      # 15 segundos, archivo /tmp/fulano_HHMMSS.wav
capture-talker fulano 20   # 20 segundos

El truco está en pactl list short sources | awk '$NF="RUNNING" && monitor'=. Eso identifica el sink que ahora mismo está sacando audio (mis altavoces, en mi caso un FiiO K7), y ffmpeg graba directamente de su monitor source.

Resultado: durante la reunión, cuando alguien interesante esté hablando, capture-talker fulano y tienes una muestra perfecta lista para clonar. Después aplicas el flujo de los pasos 3 al 7.

Implicaciones éticas obvias. Hablamos de ello al final.

Bonus 2: mandar el audio generado al Telegram

El uso real de todo esto, para mí, no es generar audios para guardarlos. Es mandárselos a alguien. La cadena completa que uso:

# 1. Generar
echo "el texto que quiero que diga" | f5-say -o /tmp/v.wav menganita -

# 2. Convertir a OGG/Opus (Telegram exige este formato para voice notes)
ffmpeg -y -i /tmp/v.wav -c:a libopus -b:a 64k /tmp/v.ogg

# 3. Mandar como nota de voz (no como audio adjunto)
BOT=$(cat /run/agenix/telegram-bot-token)
CHAT=$(cat /run/agenix/telegram-chat-id)
curl -sf -X POST "https://api.telegram.org/bot${BOT}/sendVoice" \
  -F chat_id="$CHAT" -F voice=@/tmp/v.ogg

# 4. Limpiar
rm -f /tmp/v.wav /tmp/v.ogg

Lo importante: sendVoice con un OGG/Opus produce la burbuja típica de WhatsApp/Telegram, no un audio reproducible con player. Si mandas un WAV o MP3 con sendAudio, se ve como un archivo adjunto y delata que es generado. La burbuja de voz pasa desapercibida.

Lecciones que aprendí a base de hostias

Algunas cosas que no están en la documentación oficial pero que te ahorran mucho tiempo:

No leas URLs, IDs ni hashes en el audio

Si pides al modelo que genere "el commit es 7f3a9b21", va a leer literal "siete efe tres a nueve be dos uno". Suena horrible y no se entiende. Pon esos detalles en el caption del mensaje, no en el audio. El audio es narrativo, no técnico.

Transcribe foneticamente las siglas y números

"F5" se lee mejor como "efe cinco". "RTX 2060" como "ere te equis dos mil sesenta". "IA" como "Inteligencia Artificial" o "i a" si quieres letras. F5-TTS no tiene un módulo de letrear siglas; lee lo que pones.

Cuidado con los textos largos

Por encima de 1500-2000 caracteres, F5 puede empezar a:

Si necesitas un audio largo, trocea el texto en chunks de unos 1000 caracteres, genera cada uno y concaténalos con ffmpeg.

El modelo en español es CRUCIAL

El modelo base de F5-TTS es bilingüe (inglés + chino). Para español, jpgallegoar/F5-Spanish marca la diferencia entre "se entiende lo que dice" y "parece nativo". No te molestes con el modelo base si vas a generar en español.

La primera generación tarda mucho

La primera vez que invocas F5 carga el modelo en VRAM y eso lleva entre 30 y 90 segundos en una RTX 2060. Después, mientras el proceso sigue vivo, las generaciones son rápidas. Si vas a hacer batch, mantén el proceso abierto.

Implicaciones éticas

No puedo cerrar este post sin decirlo: clonar la voz de alguien sin su permiso es una putada y, en muchas jurisdicciones, ilegal. La tecnología que acabo de explicar permite generar audios indistinguibles de los reales, y eso tiene consecuencias.

La regla simple que aplico:

Si vas a hacer esto para cachondear con alguien cercano, avisa antes y enseña el resultado. Si lo vas a usar para algo serio (un asistente personal con tu propia voz, por ejemplo), pues adelante. Pero no clones la voz del CEO para mandar audios fraudulentos: hay gente cumpliendo condena por menos.

Las plataformas grandes (ElevenLabs, OpenAI) tienen detección de voces clonadas y filtros activos. Las herramientas locales como F5-TTS no tienen nada. La responsabilidad está entera en ti.

Conclusión

En 2026, clonar una voz con calidad alta es un fin de semana de cacharreo, una RTX modesta y software MIT. La barrera técnica es prácticamente nula. La barrera real es ética y de criterio.

Si quieres usarlo bien: pídele permiso a la persona, hazle reír con el resultado, y guarda los samples para el futuro. Es una forma curiosa de archivar voces de gente cercana en un formato del que se pueden generar mensajes nuevos.

Si quieres usarlo mal: te recomiendo que no.

Recursos

Comparte este post:

Es tu post

Estas seguro? Esto no se puede deshacer.

Comentarios (0)

Sin comentarios todavia. Se el primero!

Deja un comentario