Pular para o conteúdo

Otimização de latência em agentes de voz: guia passo a passo

Publicado

OuvirOuça este artigo

A resposta de um agente de voz depende do tempo total entre o momento em que o usuário termina de falar e o início da resposta do agente. Esse atraso raramente é causado por um único componente lento. Ele se acumula em várias etapas independentes, cada uma contribuindo com dezenas ou centenas de milissegundos, e para reduzir é preciso saber quanto tempo cada etapa consome.

Otimizar a latência de um agente de voz é identificar onde esse tempo está escondido e recuperá-lo etapa por etapa.

Este artigo complementa o guia conceitual sobre latência. Enquanto aquela página explica o que é latência, aqui você encontra detalhes sobre arquitetura e medições, para que você saia com um orçamento de latência mensurável e ações práticas para aplicar.

Resumo rápido

  • O tempo até o primeiro áudio representa todo o pipeline, não apenas o tempo de inferência de um modelo.
  • O tempo até o primeiro token do LLM e o endpointing são os maiores responsáveis pela latência.
  • Sobrepor etapas, em vez de executá-las em série, recupera a maior parte do tempo.
  • Streaming, escolha do codec e ajuste do buffer do player ajudam a economizar milissegundos.
  • Você deve medir por região no seu próprio ambiente, reportando P50 e P95.

Definindo o orçamento de latência do agente de voz

O orçamento de latência é o tempo total até o primeiro áudio, distribuído entre as etapas do pipeline, com cada etapa recebendo uma cota que deve somar menos que o seu objetivo. Definir esse orçamento é o primeiro passo e também onde muitos erram, pois engenheiros podem confundir dois números parecidos, mas com significados diferentes.

O primeiro é a latência de inferência do modelo: o tempo que o modelo leva para gerar uma resposta. Para nossos modelos Flash, isso é cerca de 75ms para entradas curtas, sem contar rede e aplicação. Esse número é interno e serve para comparar modelos. Não é o tempo que o usuário percebe.

Do ponto de vista do usuário, o foco é o tempo até o primeiro áudio (TTFA): o tempo entre o usuário parar de falar e ouvir a primeira resposta do agente. O TTFA sempre é maior que a latência de inferência de qualquer modelo, pois soma todas as etapas do pipeline.

Um agente de voz em cascata passa por cinco etapas:

  • captura (microfone) -> STT -> LLM -> TTS -> reprodução

O áudio é capturado do microfone, transcrito em texto, enviado para o modelo de linguagem, o texto é sintetizado em voz e essa voz é armazenada em buffer e reproduzida. Cada etapa adiciona latência, e em várias delas o maior custo não é o que você imagina.

Veja um exemplo para um agente em inglês com servidores próximos do usuário. Os números são faixas ilustrativas, não garantias.

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, os dois maiores responsáveis pela latência são o tempo até o primeiro token do LLM e o atraso do endpointing no início da cadeia.

A tabela ajuda a visualizar o pipeline, mas sugere que as etapas rodam em série, o que não acontece. Muitas otimizações de latência vêm da sobreposição dessas etapas, e é aí que a maior parte do tempo é recuperada.

Speech to Text: otimização da latência de transcrição e endpointing

A transcrição é a segunda etapa do pipeline, e seu maior custo não é a transcrição em si, mas decidir quando o usuário terminou de falar. Esta seção cobre ambos os pontos para ajudar você a otimizar a latência.

A transcrição ocorre antes de chegar ao LLM.Scribe v2 em Tempo Real (scribe_v2_realtime) retorna transcrições parciais em cerca de 150ms e transmite em blocos de áudio, então a transcrição é formada enquanto o usuário ainda fala. Suporta PCM de 8kHz a 48kHz e codificação mu-law, importante para a escolha do codec. Os parciais de 150ms têm baixo custo.

O maior custo de latência é o endpointing: o momento em que o sistema decide que o usuário realmente terminou sua vez.

A Detecção de Atividade de Voz (VAD) segmenta a fala pelo silêncio, e é aí que o tempo se acumula. Se você espera, por exemplo, 700ms de silêncio para encerrar a vez, adiciona 700ms a cada interação, além da transcrição. Esse atraso não aparece em benchmarks de precisão, mas é sentido em conversas reais. Geralmente é a maior latência controlável do pipeline, e por ser controlável, é um bom ponto de partida.

O endpointing é um equilíbrio entre resposta rápida e evitar interrupções. Um limiar de silêncio curto faz o agente responder rápido, mas pode cortar o usuário em pausas naturais. Um limiar longo é seguro, mas deixa o agente lento. Na prática, três mudanças otimizam a latência no speech to text:

  1. Ajuste fino do limiar de silêncio:Reduza o limiar ao menor valor que não corte as pausas naturais dos usuários e meça a taxa de interrupção em produção, em vez de adivinhar.
  2. Inclua um evento de controle físico: Use controle manual quando sua aplicação souber que a vez terminou por outro sinal (soltar push-to-talk, evento de interface), em vez de esperar o temporizador do VAD.
  3. Sobreponha com o processamento do LLM:Envie parciais estáveis para o LLM antes do final. Se o texto final mudar, revise. Isso esconde o atraso do endpointing atrás do processamento do prompt do LLM.

Para mais detalhes, o Scribe v2 Realtime está explicado na página de recursos de speech to text e na página do produto de transcrição de voz em tempo real.

A contribuição do LLM para a latência

O modelo de linguagem geralmente é o maior responsável pelo TTFA, então é onde a sobreposição traz mais ganhos. O ponto principal é que o agente não precisa da resposta completa para começar a falar.

A melhor estratégia é transmitir tokens do LLM para o TTS assim que chegam, em blocos por frase ou oração. O ideal é armazenar tokens até o fim de uma frase, sintetizar essa frase enquanto a próxima ainda está sendo gerada:

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 conversas longas, prefira o WebSocket de Transformar Texto em Áudio, assim a conexão aberta recebe texto incrementalmente sem precisar reabrir a cada frase. Só o tempo em que o modelo está gerando áudio conta para o limite de concorrência, então um WebSocket aberto e ocioso praticamente não tem custo.

Transformar Texto em Áudio: streaming e escolha de voz

A etapa de transformar texto em áudio é onde você pode controlar a latência com mais precisão. Os dois principais fatores são: como transmitir o áudio e qual voz escolher.

O modelo Flash v2.5 (eleven_flash_v2_5) é o ideal para agentes. Ele faz a inferência em cerca de 75ms para entradas curtas, suporta 32 idiomas e aceita até 40.000 caracteres por requisição.

Os 75ms referem-se apenas à inferência. O TTFA do TTS é maior porque inclui ida e volta da rede e agendamento do servidor.

O maior fator aqui é o streaming. Se você pedir o áudio completo e esperar, o usuário só ouve depois que tudo é sintetizado. Se usar streaming, o usuário ouve o primeiro trecho assim que ele é gerado, e o resto chega enquanto ele já está ouvindo. O streaming não deixa o modelo mais rápido, mas começa a entregar o áudio enquanto ainda está sendo gerado.

O guia de streaming explica o streaming HTTP, e o guia de WebSocket em tempo real mostra como usar WebSocket para receber tokens do LLM.

Inicialize o cliente uma vez e reutilize em todas as chamadas:

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

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

Depois, configure o stream e encaminhe conforme os dados chegam:

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
}

O outro fator é a escolha da voz, que também impacta a latência. Vozes padrão, vozes sintéticas e Clones Instantâneos (IVC) sintetizam mais rápido que Clones Profissionais (PVC), pois PVCs têm mais complexidade e aumentam o tempo de geração. Para agentes com requisitos rígidos de latência, a combinação de Flash com IVC ou voz padrão é a opção mais rápida.

Escolha do tamanho dos blocos de streaming

Com tokens indo para o TTS e áudio voltando, a próxima decisão é o tamanho dos blocos e quanto o player armazena antes de começar.

Blocos menores chegam ao player mais rápido, reduzindo a latência inicial, mas geram mais mensagens e um pequeno custo extra por bloco. Blocos maiores são mais eficientes para transporte, mas fazem o usuário esperar mais pelo primeiro. Para agentes interativos, prefira blocos menores no início da fala, pois o primeiro bloco é o mais esperado; os seguintes chegam enquanto o áudio já está tocando e seu tamanho importa menos.

O player é responsável por boa parte da latência restante. A maioria dos players não começa a tocar no primeiro byte. Eles armazenam um pouco para evitar cortes se o stream atrasar. Um buffer padrão de 500ms é comum e é somado diretamente à latência percebida. Reduzir esse valor diminui o TTFA, mas aumenta um pouco o risco de cortes, e o valor ideal depende da variação de rede entre seu servidor e o cliente:

  • Em conexões estáveis (reprodução no servidor, cliente próximo), um buffer de 50 a 150ms costuma ser seguro e reduz bastante o TTFA.
  • Em conexões móveis ou entre regiões, um buffer maior evita falhas audíveis que são piores que a latência extra.

A configuração ideal depende do seu caso de uso e das prioridades.

Escolha de codec

O destino do áudio deve definir o codec solicitado. Retornamos formatos como mp3_44100_128, mp3_22050_32, pcm_16000, pcm_24000 e ulaw_8000. Usar o formato nativo do transporte elimina uma etapa de transcodificação e ajuda na otimização da latência.

Para telefonia, como Twilio e similares, use ulaw_8000. A rede telefônica é 8kHz mu-law de ponta a ponta, então pedir esse formato evita transcodificação e corresponde ao esperado pela operadora. Não há vantagem em sintetizar áudio de alta fidelidade que será reduzido pela rede; isso só adiciona latência sem ganho audível.

Para WebRTC e reprodução em navegador, use PCM (pcm_24000 ou pcm_16000) ou MP3. PCM é sem compressão, então não há etapa de decodificação no cliente, o que reduz um pouco a latência por bloco e é útil ao alimentar pipelines de áudio direto. MP3 é mais compacto, o que ajuda em conexões limitadas, com o custo de uma decodificação leve no cliente.

Geografia e distância de rede

Todas as otimizações acima assumem que os dados percorrem distâncias curtas. A geografia define o limite mínimo do seu orçamento de latência, então vale a pena analisar antes de ajustar qualquer outra coisa.

Atendemos requisições a partir de clusters na América do Norte, Europa e Sudeste Asiático, roteando cada pedido para o cluster mais próximo automaticamente. O tempo de ida e volta na internet pública costuma variar de 20 a 200ms, dependendo da proximidade, e não pode ser reduzido sem mudar a localização da infraestrutura.

Um agente que parece instantâneo em San Francisco, perto de um cluster norte-americano, pode parecer lento para um usuário no Sul da Ásia, cujo tráfego cruza o oceano duas vezes por interação.

A solução é colocar seus servidores próximos dos usuários, não só de nós. Se seus usuários estão na Europa, rode o backend do agente na Europa para encurtar o caminho usuário-servidor; nosso roteamento cuida do caminho servidor-modelo a partir de um cluster próximo.

Medindo a latência do agente de voz por conta própria

Os números da tabela de orçamento de latência acima são faixas ilustrativas para planejamento. Os números reais devem vir de um script como este, rodando no seu próprio ambiente.

A instrumentação abaixo mede o TTFA da etapa de TTS isoladamente, do pedido ao primeiro bloco de áudio, em vários testes, e mostra os percentis. Rode a partir da mesma região dos seus servidores, não do seu computador de desenvolvimento. Assume o cliente elevenlabs já inicializado:

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`);

Alguns pontos importantes:

  • Reporte P50 e P95:Foque nesses valores, não na média. A média esconde os piores casos, e são eles que fazem o agente parecer instável. P95 é a experiência de uma a cada vinte interações.
  • Teste por localização: Rode o mesmo script em cada região atendida e mantenha os resultados separados.
  • Espaçamento para precisão:Espaçe as requisições (como no setTimeout acima). Se disparar todas de uma vez, você mede sua própria fila, não o serviço. Ao exceder o limite de concorrência, as requisições entram em fila por prioridade, o que normalmente adiciona cerca de 50ms, e acima da capacidade você recebe HTTP 429.
  • Meça toda a cadeia de latência:Aplique o mesmo padrão de medição nas outras etapas. Meça a finalização do STT, o primeiro token do LLM e o início do player usando performance.now(), assim você preenche a tabela de orçamento com seus próprios números e vê onde atacar primeiro.

Seguindo essas dicas, você conseguirá medir a latência do agente de voz por conta própria. A partir daí, terá um caminho claro de prioridades para atacar.

O que mais reduz a latência do agente de voz?

Se você quer ações rápidas, estas são as mudanças com maior impacto.

Em ordem de impacto, use os métodos abaixo para reduzir a latência do agente:

  • Inicie o processamento do LLM com parciais estáveis do STT para esconder o atraso do endpointing.
  • Transmita tokens do LLM para o TTS em limites de frases, assim a síntese da primeira frase ocorre enquanto a segunda ainda está sendo gerada.
  • Transmita o áudio do TTS para o player e ajuste o buffer para o menor valor que sua rede suporta.
  • Use Flash com voz padrão ou IVC para o TTS mais rápido e combine o codec com o transporte (ulaw_8000 para telefonia, PCM ou MP3 para navegador/WebRTC).
  • Coloque seus servidores próximos dos usuários e meça por região, pois os caminhos de rede são reais e diferentes.

Para técnicas mais avançadas, veja o guia de otimização de latência para desenvolvedores. Para um ponto de partida completo, o API quickstart e o guia de streaming trazem exemplos práticos.

Quer acesso mais rápido a agentes otimizados?ElevenAgents já implementa esse pipeline com otimizações de sobreposição.

Crie agentes de voz com baixa latência usando ElevenAgents

Otimizar a latência de agentes de voz exige medir cada etapa e sobrepor as etapas para que as mais lentas rodem enquanto outras já estão em andamento. Você pode construir e ajustar esse pipeline manualmente, usando os padrões acima, ou começar com um pipeline já otimizado.

O ElevenAgents implementa toda essa cadeia, do streaming de STT ao envio token a token para o LLM e TTS Flash, com técnicas de sobreposição já integradas. Em vez de começar do zero, você só ajusta os limites para a performance que mais importa para você.

Comece usando o ElevenAgents para criar um agente hoje ou fale com vendas para saber mais.

Perguntas frequentes sobre otimização de latência em agentes de voz

Artigos relacionados

Crie com o áudio de IA da mais alta qualidade