¿Cómo se añade aislamiento de hablante a un worker de LiveKit Agents?
Ejecuta el SDK de Anecho sobre el audio entrante dentro del stt_node del worker, en saltos de 240 muestras a 16 kHz. No existe un paquete de plugin para LiveKit, así que este artículo muestra el código que escribes tú, con notas de remuestreo y los números.
Se añade aislamiento de hablante a un worker de LiveKit Agents pasando los frames de audio entrante por el SDK de Anecho antes de que lleguen a la etapa de voz a texto, en saltos de 240 muestras a 16 kHz. No existe un paquete livekit-plugins-anecho; no hemos publicado ninguno. Lo que sigue es el contrato del SDK aplicado a los tipos de frame de LiveKit, como código que es tuyo.
El contrato
El SDK tiene tres objetos: Model (el archivo .anecho de tu panel), Processor (float32 de entrada, el mismo número de muestras de salida, 15 ms detrás) y UsageReporter (el latido de la licencia; envía duraciones, nunca audio). El modelo trabaja a 16 kHz en saltos de 240 muestras. Las primeras 240 muestras de un flujo salen como silencio, que es el retardo algorítmico.
El bucle de frames
En Agents, stt_node recibe un iterador asíncrono de rtc.AudioFrame. Lo envolvemos, reagrupamos en saltos, ejecutamos el procesador y entregamos frames de la misma forma.
import os
import numpy as np
from scipy.signal import resample_poly
from livekit import rtc
from livekit.agents import Agent
from anecho import Model, Processor, UsageReporter
RATE, HOP = 16_000, 240 # model rate; 240 samples = 15 ms
reporter = UsageReporter(os.environ["ANECHO_API_KEY"])
model = Model.from_file("anecho.ai_focus_model_16khz_v8_2.anecho") # from your dashboard
class IsolatedAgent(Agent):
async def stt_node(self, audio, model_settings):
async def isolated():
proc = Processor(model, reporter.ensure_license()) # one per call
reporter.attach(proc)
reporter.start()
pending = np.zeros(0, dtype=np.float32)
async for frame in audio: # rtc.AudioFrame, int16
x = np.frombuffer(frame.data, dtype=np.int16).astype(np.float32) / 32768.0
if frame.num_channels > 1: # mix down to mono
x = x.reshape(-1, frame.num_channels).mean(axis=1)
if frame.sample_rate != RATE: # e.g. 48000 -> 16000
x = resample_poly(x, RATE, frame.sample_rate).astype(np.float32)
pending = np.concatenate([pending, x])
while len(pending) >= HOP:
block, pending = pending[:HOP], pending[HOP:]
y = proc.process(block) # same length out, 15 ms behind
pcm = (np.clip(y, -1.0, 1.0) * 32767).astype(np.int16)
yield rtc.AudioFrame(
data=pcm.tobytes(), sample_rate=RATE,
num_channels=1, samples_per_channel=HOP,
)
return Agent.default.stt_node(self, isolated(), model_settings)
Es un boceto contra el hook Agent.stt_node de Agents 1.x. No hemos medido un worker de LiveKit en vivo, así que comprueba la firma del hook con tu versión de Agents y pruébalo con tu propio tráfico.
Notas de remuestreo
- Los frames de LiveKit son int16 y suelen ir a 48 kHz o 24 kHz. El modelo quiere float32 a 16 kHz, así que remuestrea antes del procesador con un filtro polifásico adecuado (
resample_polyarriba), no descartando muestras. - Remuestrea una sola vez. Si tu STT también remuestrea, el audio aislado a 16 kHz ya es lo que quieren la mayoría de los reconocedores.
- Un tramo de telefonía llega a 8 kHz. Subir a 16 kHz no recupera ancho de banda; ver 8 kHz es donde la IA de voz se rompe.
- Conserva una derivación sin procesar si además grabas o tienes un segundo consumidor; ver el pipeline dividido.
Coste y la alternativa de plataforma
| Elemento | Valor | Fuente y fecha |
|---|---|---|
| Retardo algorítmico | 15 ms | Null Test, 2026-08-14 |
| Factor de tiempo real, un hilo de CPU | 0.067 | Null Test, 2026-08-14 (Apple M1 Max) |
| Peor tiempo de bloque, p99 | 3.96 ms | Null Test, 2026-08-14 |
| Nuestra tarifa de entrada tras 10,000 minutos gratis al mes | $0.0010 por minuto | anecho.ai/pricing |
| Aislamiento de voz de LiveKit Cloud, sobre la cuota del plan | $0.0012 por minuto | livekit.com/pricing, consultado el 2026-10-15 |
LiveKit Cloud vende el aislamiento de voz como una partida medida, cubierta por modelos de Krisp y ai-coustics (livekit.com/pricing y docs.livekit.io, consultados el 2026-10-15). Si ejecutas tu worker en LiveKit Cloud y uno de esos huecos te sirve, es un camino razonable. Ejecutar el SDK tú mismo mantiene el audio en tu proceso y funciona donde corra el worker. Los dos precios no son comparables uno a uno: el nuestro es por minuto procesado en una escala publicada, el suyo es por plan. Si el aislamiento ayuda a tu tráfico es una medición, no un valor por defecto: cómo evaluar el aislamiento de hablante.
FAQ
¿Hay un plugin de Anecho para LiveKit Agents?
No. No hay un paquete de plugin publicado. El SDK es una biblioteca de Python y Node, y este artículo muestra el código de integración.
¿Dónde va el procesador en el pipeline de LiveKit?
Sobre el audio entrante, antes de la etapa de voz a texto, en el hook stt_node.
¿Cuánta latencia añade?
15 ms de retardo algorítmico, medidos en Null Test el 2026-08-14 con un factor de tiempo real de 0.067 en un hilo de CPU.