Construye agentes conversacionales locales con el pipeline VAD → STT → LLM → TTS de Hugging Face
Aprende a construir agentes de voz completos usando el framework speech-to-speech de Hugging Face. Este curso cubre el pipeline completo: detección de actividad de voz (VAD), transcripción a texto (STT), generación de respuestas con modelos de lenguaje (LLM), y síntesis de voz (TTS), todo con modelos open-source y ejecutable en local.
Los agentes de voz son sistemas capaces de mantener conversaciones habladas con humanos. A diferencia de los chatbots tradicionales, procesan audio directamente: escuchan, entienden, razonan y responden con voz. Ejemplos conocidos incluyen Alexa, Siri y Google Assistant, pero hasta hace poco construir uno propio requería APIs cerradas y costosas.
El proyecto speech-to-speech de Hugging Face cambia eso: ofrece un pipeline open-source, modular y extensible que puedes ejecutar en tu propio hardware. Está compuesto por cuatro etapas encadenadas:
| Etapa | Función | Tecnología por defecto |
|---|---|---|
| VAD | Detectar cuándo el usuario habla | Silero VAD v5 |
| STT | Convertir audio a texto | Parakeet TDT / Whisper |
| LLM | Generar respuesta textual | OpenAI-compatible / Transformers |
| TTS | Convertir texto a voz | Qwen3-TTS / Kokoro |
El pipeline se usa en producción dando voz a miles de robots Reachy Mini en Hugging Face. En este curso aprenderás a montarlo, configurarlo y desplegarlo paso a paso.
Todo el stack es open-source. Puedes ejecutar el pipeline 100% local sin depender de ninguna API externa si tienes suficiente hardware (GPU recomendada).
El pipeline es una cascada de cuatro componentes que se ejecutan en hilos independientes comunicados por colas. Cada componente es completamente intercambiable mediante flags de línea de comandos.
[Micrófono] → [VAD] → [STT] → [LLM] → [TTS] → [Altavoz]
↑ ↓
Buffer de audio Buffer de audio
Detalle del flujo:
| Modo | Transporte | Cuándo usarlo |
|---|---|---|
realtime | WebSocket (protocolo OpenAI Realtime) | Construir apps o dispositivos contra una API de voz estándar |
local | Micrófono y altavoces del equipo | Hablar directamente con el pipeline, sin cliente adicional |
websocket | PCM raw sobre WebSocket | Cliente personalizado mínimo sin protocolo Realtime |
socket | PCM raw sobre TCP | Modelos en servidor remoto con cliente ligero |
El modo realtime es el más potente: sigue el protocolo OpenAI Realtime, lo que significa que cualquier cliente que hable ese protocolo puede conectarse a tu servidor self-hosted.
El framework requiere Python 3.10+ y se instala con un solo comando pip. Vamos a ponerlo en marcha:
pip install speech-to-speech
Esto instala el pipeline con los backends por defecto:
export OPENAI_API_KEY="sk-..."
speech-to-speech
Esto inicia un servidor Realtime en ws://localhost:8765/v1/realtime usando Parakeet TDT para STT local, un LLM compatible con OpenAI y Qwen3-TTS para la salida de voz.
Desde una segunda terminal, ejecuta el cliente integrado:
python scripts/listen_and_play_realtime.py --host 127.0.0.1 --port 8765
Para una experiencia fluida necesitas al menos 8 GB de RAM y preferiblemente una GPU NVIDIA con CUDA 12+. En Apple Silicon (M1+) funciona muy bien con MLX. Sin GPU, el pipeline funcionará pero con mayor latencia.
git clone https://github.com/huggingface/speech-to-speech.git
cd speech-to-speech
uv sync
El VAD es el primer componente del pipeline. Su trabajo es detectar cuándo una persona está hablando, determinar los límites de cada intervención y gestionar el turn-taking (quién habla en cada momento).
El VAD por defecto es Silero VAD v5, un modelo pre-entrenado de alta calidad que funciona en CPU y GPU. Procesa el audio en chunks y devuelve una probabilidad de actividad de voz para cada uno.
| Parámetro | Por defecto | Descripción |
|---|---|---|
--thresh | 0.6 | Umbral de probabilidad para activar detección de voz |
--min_speech_ms | 384 | Duración mínima de voz para considerarla intervención válida |
--min_silence_ms | 64 | Silencio mínimo para segmentar intervenciones |
--min_speech_continuation_ms | 192 | Histeresis para reabrir un turno que terminó hace poco |
--unanswered_reopen_ms | 2000 | Tiempo máximo para reabrir un turno sin respuesta del asistente |
speech-to-speech \
--thresh 0.5 \
--min_speech_ms 500 \
--min_silence_ms 100 \
--mode realtime
Si el asistente interrumpe demasiado pronto, sube --thresh y --min_speech_ms. Si no detecta bien el final de tus frases, baja --min_silence_ms.
El STT convierte el audio segmentado por el VAD en texto. Es el puente entre el mundo del audio y el del lenguaje escrito.
| Backend | Plataformas | Idiomas | Instalación |
|---|---|---|---|
| Parakeet TDT (por defecto) | CUDA / CPU (nano-parakeet), Apple Silicon (MLX) | 25 lenguas europeas | Built-in |
| Whisper (Transformers) | CUDA / CPU | Multilingüe | Built-in |
| Faster Whisper | CUDA / CPU | Multilingüe | [faster-whisper] |
| Whisper MLX | Apple Silicon | Multilingüe | [whisper-mlx] |
| Paraformer (FunASR) | CUDA / CPU | Chino | [paraformer] |
speech-to-speech \
--stt whisper \
--stt_model_name openai/whisper-medium \
--mode realtime
El pipeline soporta transcripciones parciales que se envían al cliente mientras el usuario sigue hablando. Se activa con el flag:
--enable_live_transcription
Parakeet TDT es el backend más rápido en GPU. Si necesitas más precisión multilingüe, usa Whisper large-v3. Para Apple Silicon, Whisper MLX ofrece el mejor rendimiento.
El LLM es el cerebro del pipeline: recibe el texto transcrito y genera una respuesta natural, incluyendo llamadas a herramientas si es necesario. Es el componente más intensivo en cómputo.
| Backend | Uso | Ejemplo |
|---|---|---|
responses-api | API compatible con OpenAI Responses API | OpenAI, HF Inference Providers, vLLM |
chat-completions | API /v1/chat/completions | vLLM, llama.cpp, OpenRouter |
transformers | Inferencia local con Transformers | Modelos de Hugging Face Hub |
mlx-lm | Inferencia local en Apple Silicon | Modelos cuantizados MLX |
Primero, sirve el modelo con llama.cpp:
llama-server -hf ggml-org/gemma-4-E4B-it-GGUF \
-np 2 -c 65536 -fa on --swa-full
Luego, conecta el pipeline a ese servidor:
speech-to-speech \
--model_name "ggml-org/gemma-4-E4B-it-GGUF" \
--responses_api_base_url "http://127.0.0.1:8080/v1" \
--responses_api_api_key "" \
--responses_api_stream
speech-to-speech \
--mode local \
--llm_backend responses-api \
--model_name "Qwen/Qwen3.5-9B:together" \
--responses_api_base_url "https://router.huggingface.co/v1" \
--responses_api_api_key "$HF_TOKEN" \
--responses_api_stream \
--enable_live_transcription
El LLM es el cuello de botella. Para baja latencia, usa modelos pequeños (gpt-4o-mini, Qwen3-4B) o servidores self-hosted con vLLM.
El TTS convierte la respuesta textual del LLM en audio sintetizado. El pipeline ofrece múltiples backends de TTS, cada uno con diferentes perfiles de calidad, velocidad y requisitos de hardware.
| Backend | Calidad | Plataformas | Instalación |
|---|---|---|---|
| Qwen3-TTS (por defecto) | ⭐⭐⭐⭐⭐ | GGML/CUDA en Linux, MLX en macOS | Built-in |
| Kokoro-82M | ⭐⭐⭐⭐ | CUDA/CPU, Apple Silicon | [kokoro] |
| Pocket TTS | ⭐⭐⭐ | CPU/CUDA | [pocket] |
| ChatTTS | ⭐⭐⭐⭐ | CUDA/CPU | [chattts] |
| MMS TTS | ⭐⭐⭐ | CUDA/CPU | [facebook-mms] |
speech-to-speech \
--tts qwen3 \
--qwen3_tts_model_name Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice \
--qwen3_tts_speaker Aiden \
--qwen3_tts_language auto \
--qwen3_tts_backend ggml \
--qwen3_tts_non_streaming_mode True
pip install "speech-to-speech[kokoro]"
speech-to-speech --tts kokoro
speech-to-speech \
--tts pocket \
--pocket_tts_voice jean \
--pocket_tts_device cpu
Qwen3-TTS ofrece la mejor calidad con voces naturales y soporte multilingüe. Para clonación de voz, Pocket TTS es la mejor opción: acepta archivos de voz personalizados.
El modo realtime expone el pipeline como un servidor WebSocket que implementa el protocolo OpenAI Realtime. Esto significa que cualquier cliente que hable ese protocolo — incluyendo el SDK oficial de OpenAI — puede conectarse a tu servidor self-hosted.
export OPENAI_API_KEY="sk-..."
speech-to-speech --mode realtime
Esto expone el endpoint ws://localhost:8765/v1/realtime.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8765/v1",
websocket_base_url="ws://localhost:8765/v1",
api_key="not-needed",
)
with client.realtime.connect(model="local") as conn:
conn.send({
"type": "session.update",
"session": {
"type": "realtime",
"instructions": "Eres un asistente de voz amigable y conciso."
}
})
for event in conn:
print(event.type)
El servidor implementa los eventos principales del protocolo:
| Dirección | Eventos |
|---|---|
| Cliente → Servidor | input_audio_buffer.append, session.update, conversation.item.create, response.create, response.cancel |
| Servidor → Cliente | speech.start, speech.stop, transcripción parcial, audio.delta, tool_calls, response.done |
Este modo es ideal para integrar el agente de voz en aplicaciones web, robots o dispositivos IoT. Cualquier cliente OpenAI Realtime funciona sin modificaciones.
El pipeline ofrece modos alternativos para diferentes escenarios de uso, desde una conversación directa en tu máquina hasta despliegues remotos con cliente ligero.
Usa el micrófono y los altavoces de tu máquina para una conversación natural:
speech-to-speech --mode local
En Mac con Apple Silicon, usa la configuración optimizada:
speech-to-speech --local_mac_optimal_settings
Esto activa automáticamente:
--device mps para usar MPS en todos los modeloslocalspeech-to-speech --mode websocket --ws_host 0.0.0.0 --ws_port 8765
Los clientes envían audio PCM raw a 16 kHz, int16, mono y reciben audio generado.
En el servidor:
speech-to-speech --mode socket --recv_host 0.0.0.0 --send_host 0.0.0.0
En el cliente:
python scripts/listen_and_play.py --host <IP-del-servidor>
El modo socket es minimalista: transmite PCM raw sin las características completas del protocolo Realtime (sin manejo de interrupciones, transcripción en vivo ni tool calls).
El pipeline incluye Docker Compose para despliegues reproducibles. Además, se usa en producción a gran escala: es el backend conversacional de miles de robots Reachy Mini de Hugging Face.
Instala el NVIDIA Container Toolkit y ejecuta:
docker compose up
El compose inicia:
8080, 12345, 12346| Caso | Descripción | Modo recomendado |
|---|---|---|
| Robots conversacionales | Reachy Mini, asistentes en ferias | Realtime server |
| Asistente de voz en casa | Control por voz, preguntas y respuestas | Local |
| Call center / IVR | Auto-attendant con IA | WebSocket / Realtime |
| Traducción simultánea | Speech-to-speech multilingüe | Realtime + language=auto |
| Juegos / VR | NPCs con voz en tiempo real | Socket (baja latencia) |
# Terminal 1: llama.cpp con Gemma 4
llama-server -hf ggml-org/gemma-4-E4B-it-GGUF \
-np 2 -c 65536 -fa on --swa-full
# Terminal 2: Pipeline con Gemma 4 local
speech-to-speech \
--mode realtime \
--stt parakeet-tdt \
--llm_backend responses-api \
--tts qwen3 \
--model_name "ggml-org/gemma-4-E4B-it-GGUF" \
--responses_api_base_url "http://127.0.0.1:8080/v1" \
--responses_api_api_key "" \
--responses_api_stream \
--enable_live_transcription
# Terminal 3: Cliente Python
python scripts/listen_and_play_realtime.py \
--host 127.0.0.1 --port 8765
Este stack 100% open-source y local es ideal para prototipado y producción. Todos los modelos (Gemma 4, Parakeet, Qwen3-TTS) son gratuitos y se ejecutan en tu hardware.
No es estrictamente necesario, pero la experiencia es mucho mejor con GPU. En CPU, el TTS y el LLM tendrán latencia alta. En Apple Silicon (M1+) funciona bien con MLX. Para GPU NVIDIA, se recomienda CUDA 12+ y al menos 8 GB de VRAM.
Sí. Usa --llm_backend transformers o sirve un modelo con llama.cpp/vLLM apuntando con --responses_api_base_url a tu servidor local. Todo el stack es open-source.
Depende del hardware y la configuración. En una GPU moderna con modelos pequeños (Qwen3-4B, Parakeet TDT, Qwen3-TTS) la latencia puede ser de 1-3 segundos. El cuello de botella suele ser el LLM.
Sí. El pipeline detecta el idioma automáticamente con --language auto si el backend STT lo soporta. Parakeet TDT cubre 25 lenguas europeas; Whisper cubre muchas más. El TTS con Qwen3-TTS es multilingüe.
Sí. El protocolo OpenAI Realtime soporta tool_calls. Puedes definir herramientas que el LLM invoque durante la conversación, como buscar información, controlar dispositivos o ejecutar código.