Avanzado 15 minAudio

Asistente de voz 100 % local: Whisper + Ollama + Piper

Un asistente de voz local escucha, entiende y responde en voz alta sin enviar jamás un solo byte a la nube. Esta guía reúne tres componentes de código abierto —Whisper para el reconocimiento de voz, un LLM servido por Ollama para el razonamiento y Piper para una voz natural en francés— en un ciclo completo que se ejecuta en tu propia máquina. Detallamos la cadena STT → LLM → TTS, el hardware recomendado y la latencia que puedes esperar en la práctica.

Por Samir K.·Actualización 2026-08-27·Probado en Windows, macOS y Linux

#¿Por qué un asistente de voz local?

Alexa, Google Assistant y Siri comparten el mismo problema: cada frase que pronuncias se envía a servidores remotos para ser transcrita e interpretada. Un asistente de voz local invierte este modelo. El micrófono, el reconocimiento, el razonamiento y la voz de respuesta funcionan todos en tu propio hardware. Nada pasa por internet y el asistente sigue funcionando incluso sin conexión.

Más allá de la privacidad, el interés está en el control. Tú eliges el modelo de lenguaje, su personalidad mediante el prompt de sistema y la voz de salida, y puedes conectarlo a tus propias herramientas —domótica, agenda, notas— sin depender de una API de terceros que puede cerrar o cambiar sus condiciones de un día para otro.

Confidencialidad
Ninguna orden vocal se registra ni analiza por un tercero. Ideal para uso doméstico o profesional sensible.
Hors-ligne
La cadena completa funciona sin internet una vez descargados los modelos.
Personalizable
El prompt del sistema, la voz, el idioma, la palabra de activación y las herramientas están todos bajo tu control.
Sin suscripción
Todo es open source. El único costo es tu hardware y la electricidad.

#La cadena STT → LLM → TTS

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

Un asistente de voz, por sofisticado que sea, no es más que una secuencia de tres etapas. Comprender esta división es la clave para diagnosticar la latencia y sustituir un eslabón sin romper el resto.

  1. 01
    STT — Speech To Text
    El micrófono capta tu voz y Whisper la convierte en texto. Es el reconocimiento de voz. La calidad depende del modelo Whisper elegido y del ruido ambiental.
  2. 02
    LLM — razonamiento
    El texto transcrito se envía a un modelo de lenguaje servido por Ollama, con un prompt de sistema que define el rol del asistente. El LLM genera una respuesta escrita.
  3. 03
    TTS — Texto a voz
    La respuesta de texto pasa a Piper, que la pronuncia en voz alta con una voz francesa. Esto es síntesis vocal.
i
Tres procesos independientes
Cada módulo es un programa separado que se comunica con los demás a través de archivos de audio, texto o llamadas HTTP. Puedes probar cada eslabón por separado antes de conectar el bucle; es muy recomendable.

La latencia percibida es la suma de las tres etapas: el tiempo de transcripción de Whisper, el tiempo de generación del LLM (el más variable) y el tiempo de síntesis de Piper. Se vuelve a tratar en detalle más abajo.

#Requisitos y equipo

Un asistente de voz local es más exigente que un simple chat de texto: Whisper y el LLM comparten la GPU, y la capacidad de respuesta cuenta. Estas son las orientaciones de hardware según el nivel de ambición.

Mínimo (solo CPU)
Whisper base + un pequeño LLM en Q4_K_M (≈2 GB), como Qwen 3.5 2B o Granite 4.2 3B. Funciona, pero debes contar con varios segundos de latencia por turno. Aceptable para la domótica, donde no se habla continuamente.
Cómodo
RTX 3060 12GB o RTX 4070 12GB. Whisper small/medium en GPU + un LLM 8-9B Q4_K_M (≈5-7 GB), por ejemplo Qwen 3.5 9B o Granite 4.2 8B. Latencia del orden de 1 a 3 segundos por turno.
Fluido
RTX 4080 16GB / RTX 4090 24GB o un Mac M4 Pro (24-48 GB de memoria unificada). Whisper medium + un LLM más potente (Gemma 4 12B ≈8 GB, o Qwen 3.8 27B ≈18 GB en un equipo con 24 GB), respuestas casi inmediatas.
Micro y audio
Basta con un micrófono USB de calidad aceptable. En Linux, PipeWire o PulseAudio; en macOS/Windows, la configuración predeterminada es adecuada.
→
Compartir el GPU de forma inteligente
Whisper y el LLM nunca trabajan exactamente al mismo tiempo: Whisper transcribe y luego el LLM responde. Un GPU de 12 GB puede alojar Whisper small y un 7B sin hacerlos funcionar simultáneamente a plena carga.

En cuanto al software, se supone que Ollama ya está instalado y funcionando. Si no es así, empieza por la guía de instalación de Ollama antes de continuar. Comprueba que el daemon responde.

Verificar Ollama
curl http://localhost:11434/api/tags
# doit renvoyer la liste JSON des modèles installés

#1. Escucha y transcripción (Whisper)

Whisper es el modelo de reconocimiento de voz de OpenAI, distribuido como código abierto. Para un uso local en tiempo real, se prefiere faster-whisper, una reimplementación optimizada que utiliza CTranslate2 y se ejecuta mucho más rápido que la versión de referencia, tanto en CPU como en GPU.

Instalar faster-whisper
pip install faster-whisper sounddevice numpy

Los modelos Whisper están disponibles en varios tamaños. Cuanto más grande es el modelo, mejor es la transcripción —especialmente en francés y en entornos ruidosos—, pero más lento es.

tiny / base
Muy rápidos, ideales para un CPU modesto o para la domótica. Transcripción correcta de órdenes cortas en francés.
small
Buena relación entre velocidad y calidad para la mayoría de los asistentes. Se recomienda como punto de partida.
medium
Claramente mejor en frases largas y acentos, pero requiere una GPU para funcionar con fluidez.
large-v3
Calidad máxima, reservada para GPU con recursos holgados si la latencia importa.

Aquí tienes una función de escucha que graba desde el micrófono y devuelve el texto transcrito. Se fuerza el idioma francés para evitar errores de detección.

ecoute.py
import sounddevice as sd
import numpy as np
from faster_whisper import WhisperModel

# device='cuda' + compute_type='float16' sur GPU ; 'cpu' + 'int8' sinon
model = WhisperModel('small', device='cuda', compute_type='float16')

def ecouter(duree=5, samplerate=16000):
    print('🎙️  Parlez...')
    audio = sd.rec(int(duree * samplerate),
                   samplerate=samplerate, channels=1, dtype='float32')
    sd.wait()
    audio = np.squeeze(audio)
    segments, _ = model.transcribe(audio, language='fr', beam_size=5)
    texte = ' '.join(seg.text for seg in segments).strip()
    print(f'📝 {texte}')
    return texte
→
Detección del fin del habla
Grabar durante un tiempo fijo es sencillo pero poco natural. Para un verdadero asistente, añade detección de actividad de voz (VAD) —la biblioteca silero-vad o la opción vad_filter de faster-whisper— para detener la grabación en cuanto dejes de hablar.

#2. Razonamiento (Ollama)

El texto transcrito se envía ahora al LLM. Ollama expone una API HTTP en http://localhost:11434; se consulta desde Python. La elección del modelo depende de tu GPU: un modelo compacto como Qwen 3.5 9B (6,6 GB, 256k de contexto, Apache 2.0) o Granite 4.2 8B (5,3 GB) en Q4_K_M ofrece un excelente equilibrio para un asistente conversacional.

Descargar un modelo
ollama pull qwen3.5:9b

El prompt del sistema es lo que transforma un LLM genérico en un asistente de voz útil. Para la voz, una instrucción clave: pedir respuestas cortas. Un bloque de texto se vuelve interminable una vez leído en voz alta.

raisonner.py
import requests

SYSTEM = (
    "Tu es un assistant vocal domestique en français. "
    "Réponds toujours de façon brève et naturelle, en une ou deux phrases, "
    "comme à l'oral. Pas de listes, pas de markdown, pas d'emojis."
)

def repondre(question, historique):
    historique.append({'role': 'user', 'content': question})
    r = requests.post('http://localhost:11434/api/chat', json={
        'model': 'qwen3.5:9b',
        'messages': [{'role': 'system', 'content': SYSTEM}] + historique,
        'stream': False,
        'options': {'temperature': 0.6, 'num_predict': 120},
    })
    reponse = r.json()['message']['content'].strip()
    historique.append({'role': 'assistant', 'content': reponse})
    return reponse
i
Seguir el hilo de la conversación
El historial que se pasa en cada llamada da memoria al asistente: recuerda la pregunta anterior. Limita su tamaño (por ejemplo, a los 10 últimos mensajes) para no ampliar el contexto y ralentizar la generación.

#3. Síntesis de voz en francés (Piper)

Piper es un motor de síntesis de voz neuronal rápido y local, diseñado por la comunidad Home Assistant (proyecto Rhasspy). Produce una voz francesa mucho más natural que los motores antiguos como espeak, sin dejar de ser lo suficientemente ligero como para funcionar en un Raspberry Pi.

Instalar Piper
pip install piper-tts

Piper funciona con voces preentrenadas, una por idioma y por timbre. Para el francés, varias voces están disponibles (fr_FR) en diferentes calidades. Cada voz es un par de archivos: el modelo .onnx y su configuración .onnx.json.

Descargar una voz francesa
# Voix fr_FR « siwis » en qualité medium
python -m piper.download_voices fr_FR-siwis-medium

Se utiliza a continuación para convertir una frase en audio y reproducirla directamente.

parler.py
import wave
import sounddevice as sd
import numpy as np
from piper import PiperVoice

voix = PiperVoice.load('fr_FR-siwis-medium.onnx')

def parler(texte):
    samples = []
    for chunk in voix.synthesize(texte):
        samples.append(np.frombuffer(chunk.audio_int16_bytes, dtype=np.int16))
    audio = np.concatenate(samples)
    sd.play(audio, samplerate=voix.config.sample_rate)
    sd.wait()
→
Elegir la calidad de voz
Las voces Piper están disponibles en x_low, low, medium y high. medium ofrece el mejor equilibrio para un asistente: una naturalidad convincente sin sobrecargar la CPU. high es más lento y solo aporta una mejora audible con altavoces de buena calidad.

#4. Armar el bucle completo

Una vez probadas las tres piezas por separado, solo queda enlazarlas en un bucle: escuchar, razonar, hablar, repetir. Aquí tienes el asistente mínimo completo, que reúne las funciones anteriores.

assistant.py
# On suppose importées : ecouter(), repondre(), parler()
historique = []

print('Assistant vocal prêt. Ctrl+C pour quitter.')
parler("Bonjour, je vous écoute.")

try:
    while True:
        question = ecouter(duree=5)
        if not question:
            continue
        if 'au revoir' in question.lower():
            parler('À bientôt !')
            break
        reponse = repondre(question, historique)
        parler(reponse)
except KeyboardInterrupt:
    print('\nArrêt.')

Eso es todo: unas cien líneas repartidas en tres archivos, y tienes un asistente de voz que escucha en francés, piensa con un LLM local y responde en voz alta, sin una sola llamada de red saliente. A partir de ahí, puedes añadir una palabra de activación (« Ok maison ») con openWakeWord, detección de actividad de voz (VAD) para la escucha continua, o conectar herramientas.

#Latencia real y optimizaciones

La pregunta que determina el éxito o el fracaso de un asistente de voz: ¿cuánto tiempo pasa entre el final de tu frase y el comienzo de la respuesta hablada? Estas son las magnitudes aproximadas observadas en una RTX 4070 con Whisper small y un modelo de 8-9B en Q4_K_M (como Qwen 3.5 9B).

Transcripción Whisper
≈ 0,3 a 0,8 s para una frase de 5 s con el modelo small en GPU. En CPU, calcula entre 2 y 4 s.
Generación LLM
El componente más variable. Un modelo de 8-9B en GPU produce la primera respuesta en ≈ 0,5 a 1,5 s según la longitud. Aquí es donde más importan un valor bajo de num_predict y un modelo rápido.
Síntesis Piper
≈ 0,2 a 0,5 s para una o dos frases con una voz medium. Muy rápido, rara vez es el cuello de botella.
Tiempo total percibido
Aproximadamente entre 1 y 3 segundos por turno en una GPU de gama media. Bajar de un segundo requiere hardware de gama alta o streaming.
→
La medida más eficaz: el streaming
En lugar de esperar la respuesta completa del LLM antes de sintetizarla, recibe la generación en streaming, frase por frase, y envía cada frase terminada a Piper mientras el LLM continúa. La voz empieza mucho antes y la latencia percibida disminuye notablemente.
Mantener los modelos cargados
Configura OLLAMA_KEEP_ALIVE para evitar que Ollama retire el modelo de la memoria entre dos preguntas: volver a cargarlo tarda varios segundos.
Respuestas cortas
Un num_predict bajo y un prompt de sistema que exige concisión reducen directamente el tiempo de generación y la duración de la lectura.
Whisper adecuado
No elijas large-v3 si small basta para tus condiciones acústicas: ahorrarás cientos de milisegundos en cada turno.

#5. Integrar en Home Assistant

Si tu objetivo es controlar una casa conectada por voz, no es necesario volver a programarlo todo. Home Assistant integra de forma nativa el pipeline «Assist», y tanto Whisper como Piper se pueden conectar mediante complementos oficiales; de hecho, se desarrollaron en este ecosistema.

  1. 01
    Instalar los complementos de voz
    Desde Ajustes → Módulos complementarios, añade «Whisper» y «Piper». Home Assistant los ejecuta localmente como servicios de STT y TTS.
  2. 02
    Crear un pipeline Assist
    En Configuración → Voz, crea un asistente: elige Whisper para el reconocimiento y Piper (voz fr_FR) para la síntesis.
  3. 03
    Conectar el LLM Ollama
    Home Assistant propone una integración « Ollama » como agente de conversación. Introduce la URL http://localhost:11434 y tu modelo para reemplazar el análisis de intención por defecto.
  4. 04
    Elegir un punto de entrada de voz
    Un satélite ESP32 (Voice PE), un teléfono antiguo o la aplicación móvil sirven de micrófono/altavoz en las habitaciones.
i
Dos enfoques complementarios
El script Python de esta guía te da un control total y sirve como entorno de aprendizaje. Home Assistant ofrece una integración domótica lista para usar. Muchos empiezan con el script para entender la cadena y luego pasan a Assist para el hogar.

#Solución de problemas

Whisper transcribe en el idioma incorrecto
Fuerza language='fr' en transcribe(). De lo contrario, una frase corta puede detectarse como inglés.
Sin sonido de salida
Verifica el dispositivo de salida de sounddevice (sd.query_devices()) y asegúrate de que la tasa de muestreo pasada a sd.play coincida con voix.config.sample_rate.
El micrófono no graba nada
Prueba sd.query_devices() para identificar el índice de entrada correcto y comprueba los permisos del micrófono (macOS) o la fuente de PipeWire/PulseAudio (Linux).
Respuestas demasiado largas e ilegibles
Refuerza la instrucción de brevedad del prompt de sistema y reduce num_predict. Un LLM demasiado prolijo arruina la experiencia de voz.
Latencia que aumenta con el transcurso de la conversación
El historial aumenta el contexto. Limítalo a los últimos N mensajes.
Ollama recarga el modelo con cada pregunta
Aumenta OLLAMA_KEEP_ALIVE (por ejemplo, a 30m) para mantener el modelo en VRAM entre turnos.

#Para ir más allá

Tu asistente de voz se basa en un LLM local bien elegido y bien configurado. Estas guías del sitio complementan la puesta en marcha:

Whisper + Ollama: transcripción y resumen
Para profundizar en la parte de audio y procesar archivos largos en lugar de trabajar en tiempo real.
LLM local para la domótica
Para conectar a tu asistente con Home Assistant y controlar la casa por voz, preservando la privacidad.
Q4, Q5, Q8: ¿qué cuantización elegir?
Para encontrar el equilibrio entre calidad de respuesta, velocidad y VRAM según tu GPU.
¿Esta guía te ha ayudado?

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