Locución y TTS
La locución impulsa la línea de tiempo. Genérala antes de construir los elementos visuales.
Elige un motor
| Motor | Ubicación | Fortaleza | Precaución |
|---|---|---|---|
| ElevenLabs | API en la nube | Mejor naturalidad, clonación de voz | De pago; clona solo voces con consentimiento |
| OpenAI TTS | API en la nube | Simple, consistente | Opciones de voz limitadas |
| Kokoro | Local | Gratuito, buena calidad, sin conexión | Requiere configuración de Python |
| Piper | Local | Rápido, funciona en CPU | Menos expresivo |
| Voz humana grabada | Micrófono | Lo más auténtico | Necesita limpieza |
Mantén las claves de API en variables de entorno o en un archivo .env que esté en .gitignore. Nunca las imprimas ni las subas al repositorio.
Prepara el guion para el habla
- Escribe números, unidades y acrónimos como se pronuncian: "veinte veintiséis", "A P I" si se debe deletrear, "gigabytes".
- Añade comas para pausas de respiración; usa un punto para una pausa completa; evita paréntesis.
- Coloca los nombres difíciles en una lista de pronunciación y pruébalos primero en una muestra corta.
- Divide en un archivo por escena (
audio/scene-01.mp3). Los archivos por escena te permiten regrabar una sola línea y mantener la temporización flexible.
Genera (ejemplo, ElevenLabs REST)
import os, requests, pathlib
def tts(text: str, voice_id: str, out: pathlib.Path) -> None:
r = requests.post(
f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
headers={"xi-api-key": os.environ["ELEVENLABS_API_KEY"], "Accept": "audio/mpeg"},
json={"text": text, "model_id": "eleven_multilingual_v2",
"voice_settings": {"stability": 0.5, "similarity_boost": 0.75}},
timeout=120,
)
r.raise_for_status()
out.write_bytes(r.content)
Los nombres de modelos y los endpoints cambian. Confírmalos contra la documentación actual del proveedor antes de usarlos.
Mide y temporiza
ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 audio/scene-01.mp3
- Apunta a 140 a 160 palabras por minuto (palabras / segundos * 60). Si una escena supera las 180 ppm, regenérala con una entonación ligeramente diferente o recorta el texto; sonará apresurada.
- No estires temporalmente el habla más de un 10 por ciento aproximadamente; sonará sintético. En lugar de eso, reescribe.
Limpia la voz grabada
# Filtro pasa altos, reducción suave de ruido, compresión, volumen
ffmpeg -i raw.wav -af "highpass=f=80,afftdn=nf=-25,acompressor=threshold=-18dB:ratio=3:attack=5:release=80,loudnorm=I=-16:TP=-1.5:LRA=11" -ar 48000 clean.wav
Recorta el silencio inicial y final:
ffmpeg -i in.wav -af "silenceremove=start_periods=1:start_threshold=-45dB,areverse,silenceremove=start_periods=1:start_threshold=-45dB,areverse" out.wav
Ensambla
# Une archivos de escena con espacios de 0.4 s
python - <<'PY'
import subprocess, pathlib
files = sorted(pathlib.Path("audio").glob("scene-*.mp3"))
parts = []
for i, f in enumerate(files):
parts += ["-i", str(f)]
n = len(files)
filt = "".join(f"[{i}:a]apad=pad_dur=0.4[a{i}];" for i in range(n)) + "".join(f"[a{i}]" for i in range(n)) + f"concat=n={n}:v=0:a=1[out]"
subprocess.run(["ffmpeg", "-y", *parts, "-filter_complex", filt, "-map", "[out]", "voiceover.mp3"], check=True)
PY
Luego mézclalo con música en audio-mixing y añade subtítulos con captions-subtitles.
Ética y derechos
- Clona una voz solo con el permiso explícito del hablante.
- Revela el uso de voz sintética donde las normas de la plataforma o la ley lo exijan.
- Revisa la licencia del proveedor de TTS para uso comercial.