Transcribir audio en español con Whisper: alucinaciones, vocabulario y quién habla
Configuración de Whisper para español, por qué inventa frases en los silencios, cómo añadir vocabulario, separar hablantes con pyannote y medir con WER.

Si en tus transcripciones aparece «Subtítulos realizados por la comunidad de Amara.org» y nadie lo dijo, no es un error tuyo: Whisper lo inventa en tramos de silencio o ruido, porque aprendió de miles de horas de vídeos subtitulados que terminaban con esa frase. Es el ejemplo más visible de un problema general. Whisper es un modelo generativo: cuando el audio no le da información, genera texto plausible igualmente.
Configuración base que evita la mitad de los problemas
faster-whisper es una reimplementación de Whisper sobre CTranslate2 que suele ser varias veces más rápida que la original con la misma calidad y menos memoria. Una configuración razonable para español:
# Convertir cualquier entrada a WAV mono de 16 kHz, el formato que usa el modelo
ffmpeg -i reunion.mp4 -ar 16000 -ac 1 reunion.wav
from faster_whisper import WhisperModel
modelo = WhisperModel("large-v3", device="cuda", compute_type="float16")
segmentos, info = modelo.transcribe(
"reunion.wav",
language="es", # no dejar que lo detecte
vad_filter=True, # descartar tramos sin voz
condition_on_previous_text=False, # reduce bucles de repetición
initial_prompt="Reunión de producto. Participan Ximena Quispe y Joaquín Ibarra. "
"Se habla de Kubernetes, PostgreSQL y el panel de facturación.",
)
for s in segmentos:
print(f"[{s.start:7.2f} → {s.end:7.2f}] {s.text}")
Cada parámetro corrige un fallo concreto. Fijar el idioma evita que un inicio con música o una frase en inglés haga que el modelo transcriba todo el archivo en otro idioma o lo traduzca. El filtro de actividad de voz (VAD) elimina los silencios antes de que el modelo pueda rellenarlos con frases inventadas. Y desactivar el condicionamiento en el texto anterior corta los bucles en los que una frase se repite decenas de veces: a cambio, la puntuación y el estilo pueden ser algo menos consistentes entre segmentos.
Vocabulario: el prompt inicial y sus límites
El initial_prompt le da al modelo un texto previo que influye en la ortografía de nombres propios, siglas y términos técnicos. Funciona porque el modelo trata ese texto como lo dicho justo antes del audio. Escríbelo como una frase natural del mismo estilo que la transcripción, no como una lista de palabras sueltas, y mantenlo breve: Whisper solo usa una parte limitada del prompt.
No esperes milagros. Mejora la ortografía de términos que el modelo ya está oyendo, pero no corrige un audio en el que el término no se entiende. Y si el prompt contiene palabras que no aparecen en el audio, en ocasiones el modelo las inserta igualmente.
Para corregir el resto, una segunda pasada con un LLM de texto puede arreglar términos y puntuación usando un glosario. Hazla con instrucciones estrictas de no reformular ni resumir, y compara longitudes antes y después: si el texto corregido es mucho más corto, el modelo resumió en lugar de corregir.
Separar hablantes
Whisper no identifica quién habla. Para eso se usa un modelo de diarización, como los de pyannote.audio, que devuelve tramos de tiempo etiquetados con hablantes anónimos (SPEAKER_00, SPEAKER_01). Después se combinan ambas salidas asignando cada segmento de Whisper al hablante con el que más se solapa en el tiempo.
def asignar_hablante(segmento, tramos_diarizacion):
mejor, solape_max = None, 0.0
for tramo in tramos_diarizacion:
solape = min(segmento.end, tramo.fin) - max(segmento.start, tramo.inicio)
if solape > solape_max:
mejor, solape_max = tramo.hablante, solape
return mejor
Funciona bien con turnos de palabra claros. Falla cuando dos personas hablan a la vez o se interrumpen con frases cortas: un segmento de Whisper puede contener palabras de dos hablantes y se asigna entero a uno. Si la atribución exacta importa (actas, entrevistas), pide marcas de tiempo por palabra a Whisper (word_timestamps=True) y asigna palabra a palabra, aunque cueste más proceso.
Para poner nombres reales a SPEAKER_00 y SPEAKER_01 necesitas una muestra de voz de cada persona o una revisión humana. No dejes que un LLM adivine nombres por el contenido: se equivocará con aplomo.
Medir con WER, normalizando antes
La tasa de error de palabras (WER) cuenta sustituciones, eliminaciones e inserciones respecto a una transcripción de referencia, dividido por el número de palabras de la referencia. Transcribe a mano entre 10 y 20 minutos de audio representativo y compara.
import jiwer, re, unicodedata
def normalizar(t):
t = unicodedata.normalize("NFKC", t.lower())
t = re.sub(r"[^\w\sáéíóúüñ]", " ", t)
return " ".join(t.split())
wer = jiwer.wer(normalizar(referencia), normalizar(hipotesis))
Sin normalizar, la puntuación y las mayúsculas inflan el WER y comparas estilos de escritura en lugar de reconocimiento. Decide también cómo tratas números («veinte» frente a «20») y aplica la misma regla a ambos textos.
El WER pesa igual todas las palabras. Confundir «de» con «del» y confundir el nombre del cliente cuentan lo mismo. Revisa además a mano los errores en nombres, cifras y términos clave, que son los que importan en el uso real.
Errores frecuentes y limitaciones
Usar el modelo más pequeño para ahorrar. Los modelos pequeños de Whisper cometen bastantes más errores en español que los grandes, sobre todo con acentos regionales y vocabulario técnico. Si el costo de GPU es el problema, prueba primero las variantes optimizadas o cuantizadas del modelo grande (como large-v3-turbo o la cuantización int8 de faster-whisper) antes de bajar de tamaño.
Audio de mala calidad. Ningún ajuste del modelo compensa un micrófono lejano en una sala con eco. Si controlas la grabación, un micrófono por persona mejora más la transcripción y la diarización que cualquier cambio de software.
Confiar en la transcripción para datos críticos. Whisper puede omitir una negación o cambiar una cifra de forma plausible. Para actas legales, consentimientos o instrucciones médicas, la transcripción automática es un borrador que requiere revisión.
¿Cómo transcribo en tiempo real?
Whisper procesa ventanas de hasta 30 segundos y no está diseñado para streaming. Las soluciones en tiempo real procesan fragmentos cortos con solapamiento y confirman el texto solo cuando se estabiliza, lo que añade latencia de uno o varios segundos. Si necesitas subtítulos en directo con latencia baja, evalúa también servicios de reconocimiento diseñados para streaming.
Configuración inicial recomendada
Convierte a WAV mono de 16 kHz, usa large-v3 con idioma fijo en español, VAD activado y condition_on_previous_text=False, y un prompt inicial con los nombres y términos de tu dominio. Transcribe a mano 15 minutos de tu audio real para medir el WER antes de cambiar ningún parámetro.


