Integración con LiveKit
Integración con LiveKit
Esta guía muestra cómo usar ElevenLabs Speech Engine como capa de voz para una sala de LiveKit. Un worker de LiveKit Agents se une a la sala como participante, se suscribe a la pista de audio del usuario, abre un WebSocket con Speech Engine y publica el audio sintetizado de Speech Engine de vuelta en la sala como su propia pista.
Arquitectura
Speech Engine acepta dos tipos de conexiones WebSocket:
- El WebSocket del cerebro al que se conecta la API de ElevenLabs. Tu servidor lo ejecuta con el SDK de Speech Engine (
engine.serve()/engine.attach()) y recibe transcripciones a las que responder. - El WebSocket de conversación al que se conectan los clientes. Los navegadores se conectan mediante un token WebRTC; los clientes que no son navegadores (como un worker de LiveKit Agents) se conectan mediante una URL firmada y transmiten audio PCM sin procesar en ambas direcciones.
El worker de LiveKit utiliza la segunda conexión. Actúa como un “cliente” de Speech Engine en nombre de los participantes de la sala de LiveKit.
El servidor del cerebro no cambia respecto a la guía rápida de Speech Engine: el worker de LiveKit sustituye al navegador como fuente de audio, pero la lógica del LLM sigue siendo la misma.
Cuándo usar este patrón
Usa el puente de LiveKit cuando la sala forme parte de la experiencia:
- Sesiones con varios participantes en las que usuarios hablan entre sí junto con el agente
- Implementaciones existentes de LiveKit en las que cambiar de transporte rompería los clientes
- Agentes de voz que comparten una sala con pantalla compartida, vídeo o chat de texto
- Llamadas SIP a LiveKit enviadas a un worker que necesitan un agente de IA en la línea
Si solo necesitas un bucle de voz entre el navegador y Speech Engine sin otros participantes, el cliente WebRTC de la guía rápida de Speech Engine es más sencillo: Speech Engine se comunica directamente mediante WebRTC con el navegador, sin necesidad de una sala de LiveKit.
Requisitos previos
- Un proyecto de LiveKit (LiveKit Cloud o un servidor autoalojado). El worker necesita
LIVEKIT_URL,LIVEKIT_API_KEYyLIVEKIT_API_SECRET. - Un Speech Engine de ElevenLabs. Sigue la guía rápida de Speech Engine para crear uno y ejecutar el servidor del cerebro.
- Python 3.9+ o Node.js 18+.
El worker puente de Node usa
@livekit/rtc-node, que actualmente está en
vista previa para desarrolladores. Para implementaciones de producción, es preferible usar el worker de Python.
Configura los formatos de audio de Speech Engine
El AudioStream de LiveKit remuestrea las pistas Opus entrantes a la frecuencia de muestreo PCM que solicites, por lo que puedes ajustarla directamente a la entrada de Speech Engine. Actualiza Speech Engine para aceptar PCM de 16 kHz como entrada de ASR y emitir PCM de 24 kHz como salida de TTS.
El PCM de Speech Engine utiliza enteros con signo de 16 bits en formato little-endian en todo el proceso. Consulta la referencia de formatos de audio para conocer otras frecuencias compatibles.
Crea el worker puente
El worker es un proceso de larga duración que se conecta a tu servidor de LiveKit, espera trabajos, se une a las salas asignadas y conecta el audio entre la sala y Speech Engine.
Genera una URL firmada de Speech Engine
El worker solicita una URL firmada de corta duración para el WebSocket de conversación de Speech Engine. La URL firmada incluye el ID del motor y una firma de un solo uso, por lo que el worker puede abrir el WebSocket sin exponer tu clave de API.
Define el punto de entrada del worker
Cada vez que se asigna el worker a una sala, se ejecuta su punto de entrada. El punto de entrada se conecta a la sala, abre un WebSocket de conversación de Speech Engine e inicia dos puentes de audio: uno para el audio del interlocutor que se envía a Speech Engine y otro para el audio sintetizado que vuelve.
El worker filtra su propio audio publicado en el controlador track_subscribed comparándolo con la identidad del participante local. Sin esta comprobación, el worker intentaría enviar su propio audio sintetizado de vuelta a Speech Engine.
Dos detalles de orden son importantes para que funcione correctamente:
- Momento de registro del listener:
TrackSubscribedse registra antes dectx.connect(). LiveKit se suscribe automáticamente a las pistas existentes durante el protocolo de conexión, y un listener registrado después podría no recibir el evento. La transferencia de audio espera unFuture/Promisepara el WebSocket de Speech Engine, por lo que puede suscribirse de inmediato y reenviar audio en cuanto se abra la conexión. - Solo TypeScript — serialización de captura:
AudioSource.captureFramede@livekit/rtc-nodelanzaInvalidStatesi se llama de forma simultánea. El controlador de TypeScript serializa las capturas con una cadena de promesas. El único bucleasync for el_to_roomde Python es secuencial por naturaleza y no lo necesita.
Asigna el worker a una sala
Como el worker tiene un agent_name, utiliza una asignación explícita: solo se une a salas cuando tu backend se lo indica. El patrón más sencillo es incluir un RoomAgentDispatch en el token de acceso de LiveKit que usa el navegador para conectarse.
Cuando un navegador usa este token para crear o unirse a una sala, LiveKit asigna automáticamente el worker puente a la misma sala.
Conéctate desde el navegador
El navegador solo necesita el cliente estándar de LiveKit; no interactúa directamente con Speech Engine.
Al hacer clic en el botón, el navegador obtiene un token de LiveKit, se une a la sala con el micrófono activado y empieza a recibir la pista de audio del agente. Se asigna el worker, que abre su sesión de Speech Engine y conecta el audio en ambas direcciones.
Referencia de formatos de audio
Speech Engine admite los siguientes formatos de audio. Configúralos en el motor mediante asr.user_input_audio_format y tts.agent_output_audio_format.
AudioStream y AudioSource de LiveKit gestionan el remuestreo por ti: puedes solicitar cualquier frecuencia de muestreo a AudioStream y el SDK la convierte desde la pista Opus subyacente de 48 kHz.
Consideraciones para producción
- Asignación explícita: Configura siempre
agent_name/agentNameenWorkerOptions. La asignación automática activa el worker para cada sala creada en tu proyecto de LiveKit, algo que rara vez querrás. - Autenticación del servidor brain: Configura un secreto compartido en Speech Engine y verifícalo en tu servidor brain, para que solo Speech Engine pueda acceder a tu ruta:
El servidor brain comprueba entonces
request.headers["x-api-key"]antes de aceptar la actualización a WebSocket. - Servidor de tokens: Genera los tokens de LiveKit y Speech Engine en el servidor. No expongas nunca
LIVEKIT_API_SECRETniELEVENLABS_API_KEYal navegador. - Higiene del bucle de eventos: Mantén el trabajo intensivo de CPU fuera del bucle de eventos del worker. La llamada a
AudioSource.capture_framey la iteración deAudioStreamson sensibles al tiempo; las llamadas síncronas largas retrasarán o descartarán eventos de interrupción. Usaasyncio.to_thread()(Python) oworker_threads(Node) para trabajo bloqueante. - Cierre: Registra
ctx.add_shutdown_callback/ctx.addShutdownCallbackpara cerrar correctamente el WebSocket de ElevenLabs. De forma predeterminada, la sala (y el trabajo) se termina cuando se va el último participante que no es un agente.