Ir al contenido

Optimización de latencia en agentes de voz: guía paso a paso

Publicado
Última actualización

EscucharEscucha este artículo

La capacidad de respuesta de un agente de voz viene determinada por el retraso total entre el momento en que un usuario termina de hablar y aquel en que el agente empieza a responder. Rara vez este retraso se debe a un único componente lento. Se acumula en varias etapas independientes, cada una aporta unas decenas o cientos de milisegundos, y reducirlo exige saber cuánto tiempo consume cada etapa.

Optimizar la latencia de un agente de voz consiste en descubrir dónde se oculta ese tiempo y recuperarlo etapa a etapa.

Este artículo complementa la guía conceptual sobre latencia. Mientras que esa página explica qué es la latencia, esta aborda la arquitectura y la medición, para que puedas definir un presupuesto de latencia con el que medir y una serie de acciones concretas.

Resumen

  • El tiempo hasta el primer audio representa todo el flujo, no el tiempo de inferencia de un único modelo.
  • El tiempo hasta el primer token del LLM y la detección de final de turno son las dos partidas más importantes.
  • Solapar etapas, en lugar de ejecutarlas en serie, recupera la mayor parte del presupuesto.
  • El streaming, la elección del códec y el ajuste del búfer del reproductor reducen milisegundos cuantificables.
  • Debes medir por región en tu propio despliegue e informar de P50 y P95.

Definir el presupuesto de latencia de un agente de voz

Un presupuesto de latencia es un objetivo total de tiempo hasta el primer audio distribuido entre las etapas del flujo; a cada etapa se le asigna un margen y la suma debe quedar por debajo de tu objetivo. Definirlo es el primer paso y también donde más suelen fallar los trabajos de latencia, porque es fácil confundir dos cifras que parecen similares pero significan cosas distintas.

La primera es la latencia de inferencia del modelo: el tiempo que un modelo dedica a generar una salida. En nuestros modelos Flash es de aproximadamente 75 ms para entradas cortas habituales, sin contar la sobrecarga de red y de la aplicación. Es una cifra interna y resulta útil para comparar modelos entre sí. No es la cifra que experimenta tu usuario.

Desde la perspectiva del usuario, debes centrarte en el tiempo hasta el primer audio (TTFA): el tiempo transcurrido desde que el usuario deja de hablar hasta que oye la primera muestra de la respuesta del agente. El TTFA siempre es mayor que la latencia de inferencia de cualquier modelo individual, porque suma todo el flujo.

Un agente de voz en cascada es una cadena de cinco etapas:

  • captura (micrófono) -> STT -> LLM -> TTS -> reproducción

El audio se captura con el micrófono, se transcribe a texto, se envía a un modelo de lenguaje, el texto del modelo se sintetiza de nuevo en voz y esa voz se almacena en búfer y se reproduce. Cada etapa añade latencia y, en varias de ellas, el mayor coste no es el que esperarías.

Aquí tienes un ejemplo desarrollado para un agente en inglés con servidores razonablemente cerca del usuario. Las cifras son intervalos ilustrativos, no garantías.

What it covers
Capture + endpointing
Mic capture, VAD/turn-detection delay before the turn is considered finished
STT finalization
Last partial to committed transcript after end-of-speech
Network (client to your server to our API)
Round-trips across the pipeline
LLM time-to-first-token
Prompt processing until the first usable token
TTS time-to-first-audio
First TTS request until first audio chunk leaves the model
Player buffering
Client-side buffer before playback begins
End-to-end TTFA
The total latency of the end-to-end pipeline
P50
Capture + endpointing
120 ms
STT finalization
60 ms
Network (client to your server to our API)
60 ms
LLM time-to-first-token
250 ms
TTS time-to-first-audio
110 ms
Player buffering
80 ms
End-to-end TTFA
~680 ms
P95
Capture + endpointing
280 ms
STT finalization
150 ms
Network (client to your server to our API)
160 ms
LLM time-to-first-token
600 ms
TTS time-to-first-audio
220 ms
Player buffering
150 ms
End-to-end TTFA
~1560 ms

Normalmente, las dos partidas de latencia más importantes son el tiempo hasta el primer token del LLM y el retraso de detección de final de turno al inicio de la cadena. 

La tabla es útil para visualizar el flujo, pero da a entender que las etapas se ejecutan estrictamente en serie, cuando no es así. Varias de las optimizaciones de latencia más importantes de los agentes de voz provienen de solaparlas, y ese solapamiento es donde se recupera la mayor parte del presupuesto indicado a continuación.

Voz a Texto: optimización de la latencia de transcripción y detección de final de turno

La transcripción es la segunda etapa del flujo, y su coste real no es la transcripción en sí, sino decidir cuándo el usuario ha dejado de hablar. Esta sección cubre ambos aspectos para ayudarte a optimizar la latencia de los agentes de voz.

La transcripción se produce antes de llegar al LLM. Scribe v2 Realtime (scribe_v2_realtime) devuelve transcripciones parciales en aproximadamente 150 ms y recibe audio en streaming por fragmentos, de modo que la transcripción se va generando mientras el usuario sigue hablando. Admite PCM de 8 kHz a 48 kHz y codificación mu-law, algo relevante para la sección de códecs más abajo. Los parciales de 150 ms tienen un coste bajo.

El mayor coste de latencia es la detección de final de turno: el momento en que tu sistema decide que el usuario realmente ha terminado su turno.

La detección de actividad de voz (VAD) segmenta el habla según los silencios, y ahí es donde se acumula el tiempo. Si esperas, por ejemplo, 700 ms de silencio antes de declarar terminado el turno, has añadido 700 ms a cada turno, además de la propia transcripción. Ese retraso es invisible en una prueba de precisión de transcripción, pero muy evidente en una conversación real. A menudo es la mayor latencia controlable de todo el flujo y, precisamente porque es controlable, es un buen punto de partida.

La detección de final de turno supone un equilibrio entre capacidad de respuesta e interrupciones. Un umbral de silencio corto hace que el agente responda rápido, pero puede interrumpir al usuario a mitad de frase durante una pausa natural. Un umbral largo es seguro, pero lento. En la práctica, los tres cambios que optimizan la latencia en Voz a Texto son:

  1. Ajusta el umbral de silencio: Redúcelo al valor mínimo que no trunque las pausas naturales de tus usuarios y, después, mide la tasa de interrupciones en producción en vez de hacer suposiciones.
  2. Integra un evento de control físico: Usa el control de confirmación manual cuando tu aplicación sepa que el turno ha terminado mediante otra señal (soltar el botón para hablar, un evento de interfaz), en lugar de esperar al temporizador de VAD.
  3. Solapa los procesos del LLM: Envía los parciales pronto a las etapas posteriores. Introduce parciales estables en el LLM y revísalos si la transcripción final difiere; es una forma de ejecución especulativa que oculta el retraso de detección de final de turno durante el procesamiento del prompt del LLM.

Para más información, Scribe v2 Realtime se describe con mayor detalle en la página sobre las capacidades de Voz a Texto y en la página de producto de Voz a Texto en Tiempo Real.

La contribución del LLM a la latencia

El modelo de lenguaje suele ser el mayor contribuyente individual al TTFA, por lo que también es donde el solapamiento más compensa al optimizar la latencia de los agentes de voz. La idea clave es que el agente no necesita toda la respuesta antes de empezar a hablar.

El patrón que recupera la mayor parte del presupuesto de latencia consiste en transmitir tokens del LLM e introducirlos en TTS a medida que llegan, agrupados por límites de frase u oración. La lógica es almacenar tokens hasta alcanzar un límite de oración y, después, sintetizar esa oración mientras se sigue generando la siguiente:

const SENTENCE_END = /(?<=[.!?])\s+/;

async function* speakLlmStream(tokens: AsyncIterable<string>) {
  let buffer = "";
  for await (const token of tokens) {
    buffer += token;
    const parts = buffer.split(SENTENCE_END);
    buffer = parts.pop() ?? ""; // keep the incomplete fragment
    for (const sentence of parts) {
      if (sentence.trim()) yield* synthesize(sentence.trim());
    }
  }
  if (buffer.trim()) yield* synthesize(buffer.trim());
}

async function* synthesize(text: string) {
  const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
    text,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  yield* stream;
}

Para conversaciones largas, prioriza el WebSocket de TTS para que una conexión abierta pueda recibir texto de forma incremental sin tener que pagar de nuevo el establecimiento de la conexión en cada oración. Solo cuenta para tu límite de concurrencia el tiempo en que el modelo genera audio activamente, así que un WebSocket abierto e inactivo es casi gratuito.

Texto a Voz: streaming y elección de voz

Texto a Voz es la etapa en la que puedes determinar la latencia con mayor precisión. Tiene dos palancas principales: cómo transmites el audio y qué voz eliges.

Flash v2.5 (eleven_flash_v2_5) es el modelo que debes usar en un agente. Ofrece aproximadamente 75 ms de inferencia para entradas cortas, admite 32 idiomas y acepta hasta 40.000 caracteres por solicitud.

La cifra de 75 ms corresponde únicamente a la inferencia. La línea de TTFA de TTS del presupuesto anterior es mayor porque, además de la inferencia, incluye el viaje de ida y vuelta por la red y la planificación del servidor.

La palanca más importante aquí es el streaming. Si solicitas el audio completo y esperas a recibirlo, el usuario espera a que se sintetice todo el clip antes de oír nada. Si lo transmites en streaming, el usuario oye el primer fragmento en cuanto se genera y el resto llega mientras ya está escuchando. El streaming no hace que el modelo sea más rápido; simplemente empieza a enviar la salida al usuario mientras sigue generándola.

La guía práctica de streaming explica el streaming HTTP, y la guía de WebSocket en tiempo real explica la vía WebSocket que te interesará al introducir tokens desde un LLM.

Inicializa el cliente una vez y reutilízalo para cada llamada a continuación:

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_API_KEY });

Después, configura un stream y reenvíalo a medida que llega:

const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
  text: "Your call is connected. How can I help today?",
  modelId: "eleven_flash_v2_5",
  outputFormat: "mp3_44100_128",
});

for await (const chunk of stream) {
  // forward each chunk to your audio sink as it arrives
}

La otra palanca es la elección de voz, que también tiene un coste de latencia. Las voces predeterminadas, las voces sintéticas y los clones de voz instantáneos (IVC) sintetizan más rápido que los clones de voz profesionales (PVC), porque los PVC implican una complejidad adicional del modelo que añade sobrecarga en cada generación. Para un agente con requisitos estrictos de latencia, la combinación de Flash y un IVC o una voz predeterminada es la opción de menor latencia.

Elección del tamaño de los fragmentos de streaming

Con los tokens entrando en TTS y el audio volviendo, la siguiente decisión es qué tamaño dar a los fragmentos y cuánto debe almacenar en búfer el reproductor antes de empezar.

Los fragmentos más pequeños llegan antes al reproductor y reducen la latencia hasta el primer byte, a costa de más mensajes y una sobrecarga ligeramente mayor por fragmento. Los fragmentos grandes son más eficientes de transportar, pero hacen que el usuario espere más al primero. Para agentes interactivos, prioriza fragmentos más pequeños al principio de la intervención, ya que el primer fragmento es el que espera el usuario; los posteriores llegan mientras el audio ya se está reproduciendo y su tamaño importa menos.

El reproductor representa una parte significativa de la latencia restante. La mayoría de reproductores de audio no empiezan a reproducir al recibir el primer byte. Almacenan una pequeña cantidad en búfer para evitar cortes si el stream se ralentiza brevemente. Es habitual un búfer predeterminado de 500 ms, que se suma directamente a la latencia percibida. Reducirlo intercambia un pequeño aumento del riesgo de cortes por un TTFA menor, y el valor adecuado depende de la fluctuación de red entre tu servidor y el cliente:

  • En una conexión estable (reproducción en el servidor o cliente ubicado conjuntamente), un búfer de 50 a 150 ms suele ser seguro y reduce de forma notable el TTFA.
  • En una conexión móvil inestable o entre regiones, un búfer mayor evita huecos audibles que resultan peores que la latencia que cuestan.

La configuración exacta que elijas depende de tu caso de uso activo y de tus prioridades.

Elección de códecs

El destino del audio debe determinar el códec que solicites. Devolvemos formatos como mp3_44100_128, mp3_22050_32, pcm_16000, pcm_24000 y ulaw_8000. Ajustar el formato nativo del transporte elimina una etapa de transcodificación y ayuda a optimizar la latencia de los agentes de voz.

Para telefonía, como Twilio y proveedores similares, usa ulaw_8000. La red telefónica utiliza mu-law de 8 kHz de extremo a extremo, por lo que solicitarlo directamente evita una etapa de transcodificación en tu flujo y coincide con lo que espera el operador. No tiene sentido sintetizar audio de mayor fidelidad que la red telefónica reducirá inmediatamente; solo añadirías latencia sin perder nada audible.

Para WebRTC y la reproducción en navegador, usa PCM (pcm_24000 o pcm_16000) o un formato MP3. PCM no está comprimido, por lo que no hay una etapa de decodificación en el cliente; esto elimina una pequeña cantidad de latencia por fragmento y resulta práctico si alimentas directamente un flujo de Web Audio. MP3 es más compacto en la red, lo que ayuda en conexiones limitadas, a costa de una ligera decodificación en el cliente.

Geografía y distancias de red

Todas las optimizaciones anteriores dan por hecho que los bytes recorren una distancia corta. La geografía establece el mínimo de tu presupuesto de latencia, así que conviene examinarla antes de ajustar cualquier otra cosa.

Atendemos solicitudes desde clústeres en Norteamérica, Europa y el Sudeste Asiático, y dirigimos cada solicitud automáticamente al clúster más cercano. El viaje de ida y vuelta por la internet pública suele ser de 20 a 200 ms según la proximidad geográfica, y no se puede reducir sin cambiar dónde se ejecuta tu infraestructura.

Un agente que parece instantáneo en San Francisco, a poca distancia de un clúster norteamericano, puede parecer lento a un usuario del sur de Asia cuyo tráfico cruza un océano dos veces en cada turno.

La solución es ubicar tus servidores de aplicaciones junto a tus usuarios, no solo junto a nosotros. Si tus usuarios están en Europa, ejecuta el backend de tu agente en Europa para que el tramo entre el usuario y tu servidor sea corto; nuestro enrutamiento se encargará entonces del tramo entre tu servidor y el modelo desde un clúster cercano.

Cómo medir tú mismo la latencia de un agente de voz

Las cifras de la tabla de presupuesto de latencia anterior son intervalos ilustrativos para planificar. Las cifras con las que lances tu producto deben proceder de un script como este, ejecutado en tu propio despliegue.

La instrumentación siguiente mide el TTFA de la etapa de TTS de forma aislada, es decir, el tiempo desde la solicitud hasta el primer fragmento de audio, a lo largo de muchas pruebas, e informa de los percentiles. Ejecútala desde la misma región donde se ejecutan tus servidores, no desde tu máquina de desarrollo. Da por hecho que usas el cliente de elevenlabs anterior:

const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";
const TEXT = "Thanks for waiting. I have pulled up your account and I can help with that now.";
const TRIALS = 50;

async function measureTtfa(): Promise<number | null> {
  const start = performance.now();
  const stream = await elevenlabs.textToSpeech.stream(VOICE_ID, {
    text: TEXT,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  for await (const _chunk of stream) {
    return performance.now() - start; // first chunk -> stop the clock
  }
  return null;
}

function percentile(values: number[], p: number): number {
  const v = [...values].sort((a, b) => a - b);
  const k = (v.length - 1) * (p / 100);
  const lo = Math.floor(k);
  const hi = Math.min(lo + 1, v.length - 1);
  return v[lo] + (v[hi] - v[lo]) * (k - lo);
}

const samples: number[] = [];
for (let i = 0; i < TRIALS; i++) {
  const ttfa = await measureTtfa();
  if (ttfa !== null) samples.push(ttfa);
  await new Promise((r) => setTimeout(r, 300)); // space requests, don't measure your own queueing
}

console.log(`trials: ${samples.length}`);
console.log(`P50:    ${percentile(samples, 50).toFixed(0)} ms`);
console.log(`P95:    ${percentile(samples, 95).toFixed(0)} ms`);

Algunas cosas que debes recordar:

  • Informa de P50 y P95: Céntrate en estos valores, no en la media. La media oculta la cola, y la cola es lo que hace que un agente parezca poco fiable. P95 representa la experiencia de un turno de cada veinte. 
  • Experimentación por ubicación: Ejecuta el mismo script desde cada región a la que prestas servicio y conserva los resultados por separado.
  • Escalona las solicitudes para mayor precisión: Separa tus solicitudes en el tiempo (el setTimeout anterior). Si las lanzas todas a la vez, medirás tu propia cola en lugar del servicio. Cuando se supera el límite de concurrencia, las solicitudes se encolan por prioridad, lo que normalmente añade unos 50 ms, y al superar la capacidad recibirás HTTP 429.
  • Mide toda la cadena de latencia: Extiende el mismo patrón de medición a las demás etapas. Encierra la finalización de STT, el primer token de tu LLM y el inicio de tu reproductor entre las mismas llamadas a performance.now(), y podrás completar toda la tabla de presupuesto con tus propias cifras y ver qué etapa debes abordar primero.

Si sigues estos consejos, podrás medir tú mismo la latencia de los agentes de voz. A partir de ahí, tendrás claras las prioridades que debes abordar primero.

¿Qué reduce más la latencia de un agente de voz?

Si buscas acciones rápidas en las que centrarte, estos son los cambios de mayor impacto.

A grandes rasgos y por orden de impacto, puedes usar los siguientes métodos para reducir la latencia del agente:

  • Inicia el trabajo del LLM con parciales estables de STT para ocultar el retraso de detección de final de turno.
  • Transmite tokens del LLM a TTS en los límites de oración para que la síntesis de la primera oración se solape con la generación de la segunda.
  • Transmite el audio de TTS al reproductor y reduce su búfer al menor valor que tolere la fluctuación de tu red.
  • Usa Flash con una voz predeterminada o un IVC para obtener el TTS de menor latencia, y ajusta el códec al transporte (ulaw_8000 para telefonía; PCM o MP3 para navegador/WebRTC).
  • Ubica conjuntamente tus servidores y tus usuarios, y mide por región, porque los tramos de red son reales y desiguales.

Para técnicas específicas más avanzadas, consulta la guía práctica para desarrolladores sobre optimización de latencia. Para contar con un punto de partida completo y ejecutable, la guía de inicio rápido de la API y la guía práctica de streaming incluyen ejemplos completos. 

¿Quieres acceder más rápido a cascadas de agentes ajustadas? ElevenAgents implementa este flujo con optimizaciones de solapamiento ya integradas.

Crea agentes de voz de baja latencia con ElevenAgents

La optimización de la latencia de un agente de voz exige medir cada etapa y después solaparlas para que las más lentas se ejecuten mientras ya se está realizando otro trabajo. Puedes crear y ajustar esa cascada manualmente a lo largo de varias iteraciones, aprovechando los patrones anteriores, o empezar con un flujo que ya incluya optimizaciones de latencia.

ElevenAgents implementa esta cascada completa, desde STT en streaming hasta la transferencia de tokens uno a uno del LLM a Flash TTS, con técnicas de solapamiento ya integradas. En vez de empezar desde cero, ajustarás los umbrales para el rendimiento que más te importe.

Empieza usando ElevenAgents para crear un agente hoy o contacta con ventas para obtener más información.

Preguntas frecuentes sobre la optimización de la latencia de agentes de voz 

Artículos relacionados

Crea con el audio IA de la más alta calidad