Intermedio 18 minAudio

Whisper + Ollama en local: transcripción 100 % sin ligne

Transcribir una reunión de una hora y luego obtener un informe estructurado: eso es exactamente lo que venden Otter, Fireflies o Tactiq, a cambio de enviar tu audio a un tercero. Whisper (de OpenAI, pero de código abierto y ejecutable sin conexión) combinado con un LLM de Ollama hace lo mismo en tu máquina, sin suscripción y sin filtraciones de datos. Esta guía construye el pipeline whisper.cpp → Ollama de principio a fin: instalación, elección del modelo, script bash, script Python y un caso concreto de transcripción local de una reunión de 1 hora.

Por Mohamed Meguedmi·Actualización 2026-08-27·Probado en Windows, macOS y Linux

#¿Por qué un pipeline whisper + ollama de transcripción local?

Una grabación de una reunión contiene nombres de clientes, cifras, decisiones estratégicas y, a veces, datos de recursos humanos. Los servicios SaaS de transcripción almacenan estos audios en sus servidores y los utilizan (según las condiciones de uso) para entrenar sus propios modelos. Para un equipo que se toma en serio la confidencialidad, esto no es negociable.

Whisper de OpenAI se puede descargar libremente y funciona sin conexión. whisper.cpp (la adaptación a C++ de Georgi Gerganov) lo ejecuta de forma eficiente en CPU y GPU, sin que Python ni CUDA sean obligatorios. Ollama, por su parte, expone un LLM local en http://localhost:11434. Ambos se conectan como bloques: audio → texto (Whisper) → resumen estructurado (Ollama). Todo permanece en tu disco.

i
El reparto de tareas
Whisper ≠ LLM. Whisper es un modelo de reconocimiento de voz (ASR): convierte sonido en texto sin formato. Resumir, dar formato y extraer decisiones es tarea de un LLM que interviene después. Estos dos modelos no tienen nada que ver y no se sustituyen entre sí.

#Prerrequisitos

El kit de IA Local

Tu ChatGPT privado y gratuito en tu máquina en 1 hora — LM Studio, Ollama, Open WebUI, tus documentos, sin nube.

  • Espacio en línea de por vida
  • PDF + archivos
  • Reembolsado 30 j
macOS, Linux o Windows (WSL2)
whisper.cpp se puede compilar en cualquier plataforma. En Windows, usa WSL2: la compilación nativa funciona, pero requiere más ajustes manuales.
Ollama instalado y operativo
Al ejecutar ollama run qwen3.5:9b, debes obtener una respuesta. Si no es así, vuelve a la guía de instalación para tu sistema operativo.
Compilador C++ y CMake
build-essential cmake en Debian/Ubuntu, Xcode Command Line Tools en macOS.
ffmpeg
Para convertir tus .m4a/.mp3/.mp4 en WAV 16 kHz, el único formato que acepta whisper.cpp como entrada.
8 GB de RAM como mínimo
Con 16 GB se trabaja cómodamente. El modelo large-v3 ocupa ~3 GB en RAM/VRAM al cargarse. Un LLM pequeño adicional, como Qwen 3.5 4B, ocupa ~3 GB.
GPU opcional
Una RTX 3060 de 12 GB transcribe 1 h de audio en ~4 min con large-v3. En Apple Silicon, Metal se activa automáticamente y es igual de rápido.

#1. Instalar whisper.cpp

Sin paquete oficial: se clona el repositorio y se compila. Son 2 minutos y se obtiene un binario portátil que puedes mover donde quieras.

Clonar + compilar para CPU
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
cmake -B build
cmake --build build --config Release -j

El binario principal queda en build/bin/whisper-cli (antes se llamaba main, previo a la reestructuración de CMake). Es el que ejecutarás para transcribir.

→
Aceleración GPU
Para CUDA (NVIDIA), agrega -DGGML_CUDA=1 al comando cmake -B build. Para Apple Silicon, Metal está activado por defecto: no hay nada que configurar. Para AMD (ROCm): -DGGML_HIPBLAS=1. El binario detecta después la GPU al iniciarse.
Variante CUDA
cmake -B build -DGGML_CUDA=1
cmake --build build --config Release -j

Instala ffmpeg por separado si no está ya instalado :

ffmpeg
# Debian / Ubuntu / WSL2
sudo apt install ffmpeg

# macOS
brew install ffmpeg

#2. Elegir el modelo adecuado de Whisper (tiny → large-v3)

Whisper existe en cinco tamaños, cada uno con dos variantes: multilingüe (por defecto) y solo en inglés (sufijo .en). Para el francés, usa la variante multilingüe. La tabla siguiente resume lo que realmente cambia.

tiny (75 MB)
Rápido pero mediocre en francés. Reservado para pruebas rápidas o para Raspberry Pi. WER (tasa de error) de aproximadamente el 30 % en francés espontáneo.
base (142 MB)
Aceptable para audio claro en inglés, flojo para audio en francés con ruido. Buena opción si tienes muy pocos recursos.
small (466 MB)
El primer nivel serio. WER ~10–12% con audio claro en francés. Transcribe 1 hora de audio en ~3 minutos con una GPU modesta.
medium (1,5 GB)
Muy buen equilibrio entre calidad y velocidad para el francés hablado en reuniones. WER ~7–8%. Reconoce bien la puntuación.
large-v3 (3.1 GB)
Estado del arte. Casi perfecto con un francés hablado con claridad, robusto frente a los acentos y al ruido de fondo. Dale prioridad cuando tengas más de 6 GB de RAM/VRAM libres.

Para transcribir una reunión en francés, la recomendación práctica es usar medium por defecto y large-v3 si tienes una GPU capaz de ejecutarlo. small es una buena alternativa para un portátil sin GPU dedicada.

Descargar un modelo
# Depuis le dossier whisper.cpp
./models/download-ggml-model.sh medium
# ou
./models/download-ggml-model.sh large-v3

Los modelos se guardan en models/ en formato ggml (el equivalente de gguf para los LLM). Puedes descargar varios tamaños y alternar entre ellos según lo que necesites.

i
Versiones cuantizadas
Si la VRAM escasea, el script admite variantes cuantizadas: large-v3-q5_0 (≈1,1 GB) o medium-q5_0 (≈540 MB). La pérdida de calidad es marginal en francés y el ahorro de memoria es real. Probar con tus propios audios.

#3. Transcribir un archivo de audio

whisper.cpp solo lee archivos WAV mono a 16 kHz. Se utiliza ffmpeg para preparar el audio, luego whisper-cli para transcribir.

Conversión a WAV 16 kHz
ffmpeg -i reunion.m4a -ar 16000 -ac 1 -c:a pcm_s16le reunion.wav
-ar 16000
Remuestreo a 16 kHz (la frecuencia de entrenamiento de Whisper).
-ac 1
Fuerza el audio mono. Whisper ignora el estéreo de todas formas.
-c:a pcm_s16le
PCM 16-bit little-endian, formato WAV no comprimido esperado.
Transcripción
./build/bin/whisper-cli \
  -m models/ggml-medium.bin \
  -f reunion.wav \
  -l fr \
  -otxt \
  -of reunion

El resultado se guarda en reunion.txt con los segmentos marcados con su tiempo correspondiente. Algunas opciones útiles que conviene conocer:

-l fr
Fuerza el uso del francés. Sin esta opción, Whisper detecta automáticamente el idioma, pero a veces se equivoca con las frases cortas.
-otxt / -osrt / -ovtt / -ojson
Formato de salida: texto plano, subtítulos SRT, VTT o JSON estructurado con timestamps. Puedes combinarlos.
-of <prefixe>
Prefijo de los archivos de salida (sin extensión).
-t 8
Número de hilos de CPU. Por defecto, whisper.cpp utiliza 4; aumenta el número a 8 o 16 en un procesador reciente.
--print-progress
Muestra una barra de progreso. Útil para archivos largos.
→
Formato JSON para el pipeline
Para continuar el procesamiento con un LLM, usa preferentemente -ojson: obtendrás los segmentos con sus marcas de tiempo de inicio y fin. Así podrás citar una marca de tiempo precisa en el resumen final («decisión tomada en 23:14»).

#4. Resumir la transcripción con Ollama

Una vez que tienes la transcripción bruta, la envías a Ollama a través de su API HTTP local. El punto de entrada /api/chat es el más directo para un uso one-shot.

Requisitos previos de Ollama
ollama pull qwen3.5:9b
# Ou pour un résumé plus fin d'une longue réunion :
ollama pull mistral-small

Para una reunión de 1 hora, la transcripción puede ocupar fácilmente entre 10.000 y 15.000 tokens. Qwen 3.5 9B admite un contexto nativo de 256k, más que suficiente. Para un resumen aún más cuidado, Mistral Small 24B (excelente en francés) cabe en menos de 16 GB de VRAM.

Prueba rápida mediante curl
curl -s http://localhost:11434/api/chat -d '{
  "model": "qwen3.5:9b",
  "stream": false,
  "options": {"temperature": 0.2, "num_ctx": 16384},
  "messages": [
    {"role": "system", "content": "Tu résumes une réunion de travail en français."},
    {"role": "user", "content": "<COLLE ICI LE CONTENU DE reunion.txt>"}
  ]
}' | jq -r '.message.content'
!
num_ctx, no por defecto
Ollama carga sus modelos con un contexto de 2048 tokens por defecto, lo que truncaría silenciosamente tu transcripción. Pasa explícitamente num_ctx (8192, 16384, 32768…) en options en cada llamada, o fija su valor mediante un Modelfile.

#5. Pipeline completo: ejemplo de resumen de reunión (1h)

Reunimos todo en un script de Python que recibe un archivo de audio como entrada y genera un informe en Markdown. Es el núcleo de un pipeline reutilizable de transcripción local con Whisper y Ollama.

Dependencias de Python
pip install requests
pipeline_reunion.py
#!/usr/bin/env python3
"""Audio -> transcription Whisper -> compte-rendu via Ollama."""
import subprocess, sys, requests, pathlib, json

WHISPER_BIN = "./build/bin/whisper-cli"
WHISPER_MODEL = "models/ggml-medium.bin"
OLLAMA_URL = "http://localhost:11434/api/chat"
LLM_MODEL = "qwen3.5:9b"

SYSTEM_CR = """Tu es un assistant qui produit des comptes-rendus de
réunion en français à partir d'une transcription brute.

FORMAT DE SORTIE (Markdown) :
# Compte-rendu
## Participants identifiables
## Sujets abordés (1 paragraphe par sujet)
## Décisions prises
## Actions à mener (avec porteur si mentionné)
## Points en suspens

RÈGLES :
- N'invente AUCUN nom, AUCUNE décision, AUCUNE action.
- Si une info manque, écris \"Non précisé\".
- Sois concis : un compte-rendu se lit en 2 minutes.
"""

def to_wav(src: pathlib.Path) -> pathlib.Path:
    dst = src.with_suffix(".wav")
    subprocess.run([
        "ffmpeg", "-y", "-i", str(src),
        "-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le",
        str(dst),
    ], check=True)
    return dst

def transcribe(wav: pathlib.Path) -> str:
    prefix = wav.with_suffix("")
    subprocess.run([
        WHISPER_BIN, "-m", WHISPER_MODEL, "-f", str(wav),
        "-l", "fr", "-otxt", "-of", str(prefix),
        "--print-progress",
    ], check=True)
    return prefix.with_suffix(".txt").read_text(encoding="utf-8")

def summarize(transcription: str) -> str:
    r = requests.post(OLLAMA_URL, json={
        "model": LLM_MODEL,
        "stream": False,
        "options": {"temperature": 0.2, "num_ctx": 16384},
        "messages": [
            {"role": "system", "content": SYSTEM_CR},
            {"role": "user",   "content": transcription},
        ],
    }, timeout=600)
    r.raise_for_status()
    return r.json()["message"]["content"]

if __name__ == "__main__":
    src = pathlib.Path(sys.argv[1])
    wav = to_wav(src)
    print(f"[1/3] Audio converti -> {wav}")
    texte = transcribe(wav)
    print(f"[2/3] Transcription : {len(texte)} caractères")
    cr = summarize(texte)
    out = src.with_name(src.stem + "_compte-rendu.md")
    out.write_text(cr, encoding="utf-8")
    print(f"[3/3] Compte-rendu : {out}")
Inicio
python pipeline_reunion.py reunion.m4a

Para una reunión de 1 hora con una RTX 3060 de 12 GB y el modelo medium: ~3 minutos para la transcripción, ~30 segundos para el resumen con Qwen 3.5 9B. Total: menos de 4 minutos, cero solicitudes de red. En un MacBook M2 de 16 GB con CPU + Metal: ~6 minutos en total.

→
Reuniones muy largas
Si la transcripción supera los 90 minutos o los 30.000 tokens, divide el texto en bloques de 10.000 tokens, resume cada bloque y luego pide al LLM que combine los resúmenes. Es el patrón clásico map-reduce. De lo contrario, la calidad del resumen se desploma, incluso si num_ctx lo admite.

#Consejos y solución de problemas

Transcripción que alucina durante los silencios
Whisper a veces inventa frases durante los silencios largos ("Subtitulado por...", "Gracias por ver"). Activa el VAD: --vad --vad-model models/ggml-silero-v5.1.2.bin (que debes descargar mediante el mismo script).
Nombres propios mal transcritos
Whisper no conoce los nombres de tus colegas. Pásalos en el prompt inicial mediante --prompt "Marie, Julien, Samir, ACME Corp, ProjetX". Se escribirán correctamente.
Audio comprimido (Zoom, Teams)
Las grabaciones de Zoom en MP4 suelen contener audio mono de mala calidad. Opta por la exportación de Zoom de "solo audio" (M4A) o graba en paralelo con OBS si la calidad es prioritaria.
Error ggml_metal_init en Mac
Has compilado sin Metal o whisper.cpp no encuentra los recursos. Recompila desde cero: rm -rf build && cmake -B build && cmake --build build --config Release -j.
Ollama: tiempo de espera agotado con un contexto grande
El cliente HTTP corta la conexión antes de terminar. Aumenta el tiempo de espera a timeout=600 (10 min) en requests. En el servidor, OLLAMA_KEEP_ALIVE=30m mantiene el modelo cargado y listo para usar.
Transcripción truncada
Si el resumen parece cortar el audio en medio, es que num_ctx es demasiado bajo. Revisa el número de tokens (wc -w en el .txt × 1.3 ≈ tokens) y ajusta num_ctx al doble.
Diarización (quién habla)
whisper.cpp no realiza diarización. Para distinguir a los hablantes, añade pyannote.audio al pipeline antes de la transcripción y luego anota cada segmento. Es otra capa que queda fuera del alcance de esta guía.
i
Costo real del hardware
Para uso diario — 2 a 3 reuniones transcritas al día — un Mac mini M4 de 16 GB (~700 €) o un mini-PC con RTX 3060 de 12 GB (~600 € de segunda mano) es más que suficiente. Es una inversión única frente a ~15 €/mes/usuario en los SaaS de transcripción, que se amortiza en menos de un año para un equipo de 5 personas.

#Para ir más allá

Tu pipeline transcribe y resume localmente. Tres vías lógicas para continuar según tus necesidades:

Informe médico con faster-whisper
La guía de transcripción de consultas utiliza faster-whisper (versión optimizada en Python), con especial atención al secreto médico, la diarización con pyannote y el cumplimiento del RGPD en el ámbito sanitario. Una variante interesante del mismo patrón.
Elegir el LLM adecuado para resumir
El resumen es el punto donde más varía la calidad. La guía para elegir la cuantización compara Q4_K_M, Q5_K_M y Q8_0: una diferencia audible en textos largos con matices.
Automatizar el pipeline con n8n
Para activar la cadena en cuanto llegue un archivo de audio (carpeta monitoreada, correo, Slack), la guía de automatización n8n + Ollama muestra cómo construir el flujo sin código.
¿Esta guía te ha ayudado?

¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.