Apresentamos o Eleven v4Conheça o Eleven v4, nosso modelo mais expressivo até agora.

Pular para o conteúdo

Transcrição de Voz em Tempo Real em menos de 200ms: Guia de arquitetura

Publicado
Última atualização

OuvirOuça este artigo

A transcrição de voz em tempo real (STT) transcreve ativamente o áudio enquanto uma pessoa fala, retornando suas palavras como texto em poucas centenas de milissegundos. Mas manter a latência de STT baixa é tanto uma questão de arquitetura quanto de modelo. Desenvolvedores precisam planejar o transporte, a divisão em chunks, a detecção de fim de fala e o caminho de captura, pois cada um acrescenta latência à equação. A ineficiência em qualquer um deles pode estourar seu orçamento de 200 ms.

Este guia oferece um sistema prático para criar pipelines de transcrição de voz em tempo real, começando pela camada de transporte. Usaremos como base o Scribe v2 Realtime, que produz transcrições parciais com cerca de 150 ms de latência do modelo, oferece suporte a mais de 90 idiomas, aceita áudio PCM (8 kHz a 48 kHz) e mu-law e disponibiliza Detecção de Atividade de Voz e controle de confirmação manual para finalizar segmentos.

Vamos acompanhar como o áudio chega ao servidor, como as hipóteses evoluem para texto confirmado, qual é o custo dos recursos no fluxo e como capturar e encaminhar o áudio corretamente.

Resumo

  • Criar sistemas de transcrição de voz em tempo real exige ajustes finos de arquitetura para garantir baixa latência em todo o pipeline.
  • WebSocket é a opção padrão adequada para a maioria dos pipelines, embora o WebRTC ofereça vários benefícios com maior complexidade.
  • A Detecção de Atividade de Voz faz a segmentação sem uso das mãos, e a confirmação manual permite que seu aplicativo assuma o controle quando sabe que a vez de fala terminou.
  • Parciais são provisórias, e finais são confirmadas; por isso, você deve renderizá-las de formas diferentes. 
  • Pequenos chunks de PCM, de cerca de 100 ms, minimizam a latência até a primeira parcial.

WebSocket vs. WebRTC para transcrição de voz em tempo real

Antes de qualquer transcrição, o áudio precisa viajar da fonte até o reconhecedor. O canal escolhido define a latência mínima para tudo que vem depois. Há duas opções viáveis para o áudio chegar à camada de transcrição.

WebSocket é um canal bidirecional, confiável, ordenado e de longa duração sobre TCP. Você abre uma conexão, envia frames binários de áudio e recebe eventos de transcrição. Ele é simples tanto no cliente quanto no servidor, atravessa proxies corporativos e firewalls que já permitem HTTPS, e é compatível com todos os navegadores e ambientes de servidor. 

A limitação do WebSocket é que ele usa TCP. Se um pacote se perde, o TCP o retransmite e retém os dados posteriores até preencher a lacuna. Em boas condições de rede, isso não é perceptível. Com perda de pacotes, ocorre bloqueio de linha de frente: uma breve parada em que o áudio se acumula e depois chega em rajada.

WebRTC foi criado para mídia em tempo real. Ele transmite mídia por UDP (via SRTP), portanto, um pacote perdido não interrompe o fluxo; o pipeline continua. Inclui um buffer de jitter que absorve variações no momento de chegada dos pacotes, negocia a travessia de NAT com ICE/STUN/TURN para que pares atrás de roteadores possam se conectar e traz seus próprios mecanismos de captura e codificação de áudio. 

Em geral, você precisa de servidores TURN para clientes que não conseguem se conectar diretamente, e o lado do servidor precisa encerrar um fluxo de mídia em vez de ler um fluxo de bytes.

Veja rapidamente essa troca de vantagens:

WebSocket
Transport
TCP (reliable, ordered)
Behavior under packet loss
Head-of-line blocking, bursty recovery
Jitter handling
Your responsibility
NAT traversal
Not needed (client-initiated)
Browser support
Universal, trivial
Server complexity
Low
WebRTC
Transport
UDP/SRTP (real-time, loss-tolerant)
Behavior under packet loss
Graceful degradation
Jitter handling
Built-in jitter buffer
NAT traversal
Requires ICE/STUN/TURN
Browser support
Universal, but more API surface
Server complexity
High (media server or SFU)

Para a maioria dos casos de uso, WebSocket é a opção certa. Use-o quando seus clientes tiverem uma conexão razoável e você controlar o caminho de captura: pipelines entre servidores, apps para desktop, apps de navegador em banda larga e a maioria dos back-ends de centrais de atendimento, nos quais o áudio já chega ao servidor por outro meio. 

Escolha WebRTC quando capturar diretamente de dispositivos de consumidores em redes móveis instáveis, quando já usar uma stack WebRTC para áudio bidirecional — por exemplo, um agente de voz que também responde falando — ou quando o comportamento em tempo real com baixa perda importar mais que a simplicidade de implementação.

O restante deste guia usa transporte WebSocket na conexão com o reconhecedor, porque ele deixa os componentes visíveis e é o ponto de partida certo para a maioria das equipes. Nada disso é específico do WebSocket, então você poderá adicionar depois uma etapa de mídia WebRTC antes dele, decodificar o áudio para PCM no servidor e encaminhar os mesmos chunks ao pipeline.

Parciais e transcrições finais: resultados provisórios explicados

Um reconhecedor em tempo real não espera uma frase completa antes de retornar resultados. Em vez disso, ele emite um fluxo contínuo de hipóteses que se refinam conforme mais áudio chega e depois as confirma. Entender a diferença entre esses dois estados separa uma transcrição que parece viva de uma que parece falha. 

Uma hipótese parcial (provisória) é a melhor estimativa do modelo com base no áudio recebido até então. As parciais são instáveis por definição. Conforme mais áudio chega, o modelo revisa palavras anteriores: "Eu quero" pode se tornar "Eu quero dois ingressos" quando o contexto posterior resolve a ambiguidade. Elas chegam rápido — é isso que descreve a latência de cerca de 150 ms — e devem ser substituídas.

Uma hipótese final é um segmento confirmado que não será alterado. Quando um segmento é finalizado, o reconhecedor segue adiante, e as hipóteses seguintes descrevem áudio posterior. As finais são o que você persiste, envia a um LLM ou armazena como transcrição.

A distinção entre parciais e finais influencia três aspectos que você errará se misturá-las:

  • Experiência do usuário: Mostrar parciais faz a transcrição parecer ao vivo: o usuário vê as palavras aparecerem enquanto fala, confirmando que o microfone funciona e que o sistema está ouvindo.
  • Detecção de fim de fala: As parciais fornecem um sinal contínuo de atividade de fala. Combinadas com VAD, elas permitem decidir quando a pessoa realmente parou de falar.
  • Tempo das etapas seguintes: Em um pipeline de agente de voz, as etapas são: áudio de entrada, depois transcrição de voz, depois um LLM, depois text to speech, então áudio de saída. Você pode iniciar trabalho especulativo com parciais e confirmá-lo com finais, reduzindo o tempo de resposta percebido, ao custo de ocasionalmente descartar trabalho especulativo.

Renderize parciais e finais de formas diferentes. Um padrão simples e eficaz é manter uma única "linha atual" mutável vinculada à parcial mais recente e confirmá-la em uma transcrição que só recebe adições quando uma final chega:

type TranscriptState = {
  committed: string[]; // finalized segments, never rewritten
  current: string;     // latest partial, overwritten on each update
};

const onPartial = (s: TranscriptState, text: string): TranscriptState =>
  ({ ...s, current: text });

const onFinal = (s: TranscriptState, text: string): TranscriptState =>
  ({ committed: [...s.committed, text], current: "" });

Visualmente, renderize o texto confirmado como estável e o atual com estilo mais claro ou em itálico, para que o usuário entenda que ele ainda pode mudar.

Detecção de fim de fala e detecção de atividade de voz (VAD)

Saber o que foi dito é apenas metade do desafio. Um reconhecedor também precisa saber quando uma ideia terminou. Essa decisão define quando você finaliza um segmento e, em um agente, quando o sistema começa a responder. 

A detecção de fim de fala é a decisão de que uma fala terminou. Finalizar cedo demais interrompe usuários no meio da frase. Finalizar tarde demais deixa um agente em silêncio depois de o usuário claramente terminar.

O Scribe v2 Realtime oferece dois mecanismos complementares:

  • A Detecção de Atividade de Voz segmenta o áudio com base no silêncio: O reconhecedor detecta quando a fala dá lugar a um silêncio contínuo e usa esse limite para finalizar automaticamente um segmento. VAD é a opção padrão adequada para interfaces conversacionais porque se adapta ao ritmo natural da fala sem que você precise acompanhar o tempo manualmente.
  • Controle de confirmação manual: O controle de confirmação manual permite que seu aplicativo decida quando finalizar o segmento atual, independentemente do silêncio. Você envia um sinal de confirmação, o reconhecedor fecha o segmento atual e emite uma final. É a ferramenta certa quando o aplicativo já sabe que a vez de fala terminou: ao soltar um botão push-to-talk, em uma ação de "enviar" ou por uma política externa de alternância de fala.

Os dois funcionam bem juntos. Um agente de voz típico usa VAD para operação sem uso das mãos e disponibiliza a confirmação manual como substituição, para que um usuário que pausa para pensar não seja interrompido, mas um usuário que toca em um botão obtenha um limite imediato.

O limite de silêncio envolve uma troca real, sem um valor universalmente correto:

  • Um tempo limite curto de fim de fala — por exemplo, finalização após cerca de 200 a 400 ms de silêncio — torna o sistema mais responsivo. Mas também interrompe usuários que fazem pausas naturais entre orações, dividindo uma ideia em vários segmentos e, em um agente, provocando uma resposta prematura.
  • Um tempo limite longo — por exemplo, cerca de 800 a 1.200 ms — tolera pausas naturais e mantém as falas intactas, ao custo de um atraso perceptível antes de o sistema reagir.

Não há uma constante global para usar aqui; ajuste o limite à interação:

  • Ditado e anotações toleram pausas mais longas, pois os usuários pensam no meio da frase. Prefira tempos limite maiores e use VAD.
  • Comando e controle, bem como agentes transacionais, se beneficiam de tempos limite menores com confirmação manual, porque as interações são curtas e diretas.
  • Pessoas multilíngues ou que não falam o idioma nativamente fazem mais pausas; portanto, reserve mais silêncio antes de finalizar.

Usar essas dicas ajuda você a criar um sistema eficaz de detecção de fim de fala e avançar rumo à transcrição de voz em tempo real.

Recursos no fluxo: detecção de idioma e diarização de locutores

O reconhecimento por streaming pode fazer mais do que gerar palavras. Dito isso, cada sinal adicional solicitado afeta a latência e a estabilidade. A regra geral é ativar apenas o que a experiência ao vivo precisa e deixar o restante para um processamento em lote.

O reconhecimento automático de idioma permite que o Scribe v2 Realtime identifique o idioma falado entre seus mais de 90 idiomas compatíveis, sem que você precise declará-lo antes. O custo é que o modelo precisa de um breve trecho de áudio para determinar o idioma com confiança; por isso, as primeiras parciais de um fluxo podem ser menos estáveis enquanto o idioma é definido. Se você já sabe o idioma, especificá-lo remove essa ambiguidade e tende a gerar parciais iniciais mais estáveis.

Diarização de locutores atribui a fala a locutores distintos, identificando quem disse o quê. Em transcrição em lote, isso é relativamente fácil porque o modelo vê o arquivo inteiro. No streaming, é mais difícil: o reconhecedor precisa atribuir um rótulo de locutor usando apenas o áudio recebido até então, e um rótulo dado ao áudio inicial pode precisar ser revisado depois que mais da voz daquele locutor for ouvida. Trate rótulos de locutor no streaming como texto parcial: provisórios até o segmento ser finalizado.

A temporização por palavra e o contexto de entidades seguem a mesma lógica. Quanto mais metadados por token você solicitar, mais dados tanto o modelo quanto a conexão precisarão transportar. Para a maioria das interfaces em tempo real, você precisa apenas do texto e dos limites de segmentos ao vivo; os metadados detalhados podem ficar para um processamento em lote após a chamada com o Scribe v2.

Formatos de áudio para streaming: PCM e mu-law

A lógica de transporte e reconhecimento recebe a maior parte da atenção, mas uma parcela surpreendente dos bugs do mundo real começa um nível abaixo: na forma como você codifica e divide o áudio em chunks. Acertar o formato e o tamanho dos chunks é a maneira mais econômica de reduzir a latência de transcrição de voz.

PCM (linear, assinado de 16 bits, little-endian) é o formato a usar quando você controla a captura. Taxas de amostragem maiores carregam mais detalhes acústicos: 16 kHz é o mínimo padrão para reconhecimento de fala e geralmente é suficiente; 8 kHz tem qualidade telefônica e perde conteúdo de alta frequência. Use a taxa que corresponde à sua fonte. Não há benefício em aumentar o áudio de telefonia de 8 kHz para 48 kHz, porque a informação não está disponível para ser recuperada.

Mu-law a 8 kHz é o formato de telefonia. Se você estiver recebendo chamadas de um provedor como a Twilio, o áudio chega em mu-law de 8 kHz e deve ser encaminhado nesse formato, em vez de transcodificado duas vezes. Corresponder ao formato da fonte evita artefatos de reamostragem e uma etapa de conversão desnecessária.

O tamanho dos chunks é o fator que mais diretamente define a latência percebida. Você envia áudio em chunks, e o reconhecedor produz parciais à medida que eles chegam. Chunks menores geram atualizações mais frequentes e menor latência até a primeira parcial; chunks maiores resultam em menos mensagens e um pouco mais de contexto por inferência. Uma faixa prática é de 20 a 250 ms de áudio por chunk. Como referência concreta, em PCM mono de 16 bits a 16 kHz, um segundo de áudio tem 32.000 bytes; portanto, um chunk de 100 ms tem cerca de 3.200 bytes.

Capturando entrada do microfone no navegador

No navegador, a ferramenta certa é a Web Audio API com um AudioWorklet. O worklet é executado na thread de renderização de áudio, recebe áudio em frames pequenos e não sofre com travamentos da thread principal como o antigo ScriptProcessorNode. Sua função é converter as amostras float nativas do navegador para PCM de 16 bits e passá-las à thread principal, que as encaminha pelo WebSocket.

O núcleo do processador do worklet é a conversão de float para PCM:

// pcm-worklet.ts - registered via audioContext.audioWorklet.addModule()
class PCMWorklet extends AudioWorkletProcessor {
  process(inputs: Float32Array[][]) {
    const channel = inputs[0]?.[0]; // mono; Float32, range [-1, 1]
    if (!channel) return true;
    const pcm = new Int16Array(channel.length);
    for (let i = 0; i < channel.length; i++) {
      const s = Math.max(-1, Math.min(1, channel[i]));
      pcm[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
    }
    // Transfer the buffer to the main thread without copying.
    this.port.postMessage(pcm.buffer, [pcm.buffer]);
    return true;
  }
}
registerProcessor("pcm-worklet", PCMWorklet);

O pipeline em código

O pipeline tem três componentes: um cliente de navegador que captura o microfone e transmite PCM para seu servidor, um servidor Node que encaminha o áudio ao Scribe v2 Realtime e retorna as transcrições, e um cliente programável que transmite PCM de um arquivo ou de uma ponte de telefonia.

O servidor encaminha os dados em vez de expor o reconhecedor diretamente ao navegador por um motivo importante: sua chave de API da ElevenLabs é secreta e nunca deve aparecer no código do cliente. O servidor mantém a chave. Se você precisar que o navegador fale diretamente com o reconhecedor, gere no servidor um token de uso único e curta duração e forneça-o ao cliente em vez da chave de API.

Cliente de navegador

O cliente abre um WebSocket para seu servidor, captura o microfone pelo worklet acima e encaminha cada frame PCM assim que ele é produzido. Eventos recebidos — já normalizados pelo servidor para { type, text } — controlam o estado de parcial/final descrito anteriormente:

// client.ts - runs in the browser. ws is an open WebSocket to your server.
const audioContext = new AudioContext({ sampleRate: 16000 });
await audioContext.audioWorklet.addModule("pcm-worklet.js");

const mediaStream = await navigator.mediaDevices.getUserMedia({
  audio: { channelCount: 1, echoCancellation: true, noiseSuppression: true },
});

const source = audioContext.createMediaStreamSource(mediaStream);
const worklet = new AudioWorkletNode(audioContext, "pcm-worklet");

// Forward each PCM frame to the server the moment it is produced.
worklet.port.onmessage = (e: MessageEvent<ArrayBuffer>) => {
  if (ws.readyState === WebSocket.OPEN) ws.send(e.data);
};
source.connect(worklet);

// Manual commit: tell the server to finalize the current segment.
const commit = () => ws.send(JSON.stringify({ type: "commit" }));

Encaminhamento pelo servidor

O servidor abre uma conexão com o reconhecedor por cliente, mantém a chave de API no servidor, encaminha o PCM binário diretamente e normaliza os eventos do reconhecedor para o formato estável { type, text } consumido pelo cliente:

// server.ts - Node, using the `ws` library. ELEVENLABS_API_KEY and the
// recognizer URL come from the environment; see the Speech to Text reference
// for the exact path and query parameters.
import { WebSocketServer, WebSocket } from "ws";

new WebSocketServer({ port: 8080 }).on("connection", (client) => {
  // The API key stays on the server, never on the wire to the browser.
  const recognizer = new WebSocket(process.env.RECOGNIZER_WSS_URL!, {
    headers: { "xi-api-key": process.env.ELEVENLABS_API_KEY! },
  });

  // Browser -> recognizer: forward binary PCM, translate control messages.
  client.on("message", (data, isBinary) => {
    if (recognizer.readyState !== WebSocket.OPEN) return;
    if (isBinary) recognizer.send(data); // raw PCM bytes
    else if (JSON.parse(data.toString()).type === "commit")
      recognizer.send(sendCommit());
  });

  // Recognizer -> browser: normalize events into a stable shape.
  recognizer.on("message", (raw) => {
    const event = parseRecognizerEvent(raw.toString());
    if (event && client.readyState === WebSocket.OPEN)
      client.send(JSON.stringify(event));
  });

  // ... open handshake, queueing pre-open audio, and teardown on close/error
});

Tudo que é específico do endpoint fica restrito às duas funções adaptadoras abaixo. Substitua os nomes dos campos pelos nomes exatos da referência de Speech to Text; o restante do pipeline não muda:

// The single place that knows the recognizer's wire format.
const sendCommit = (): string => JSON.stringify({ type: "commit" });

type NormalizedEvent =
  | { type: "partial"; text: string }
  | { type: "final"; text: string }
  | { type: "vad"; speaking: boolean };

function parseRecognizerEvent(raw: string): NormalizedEvent | null {
  const msg = JSON.parse(raw);
  if (msg.is_final === true || msg.type === "final")
    return { type: "final", text: msg.text ?? "" };
  if (msg.type === "vad") return { type: "vad", speaking: !!msg.speaking };
  if (typeof msg.text === "string")
    return { type: "partial", text: msg.text };
  return null;
}

Cliente de back-end programável

Para pipelines de back-end e para o benchmark abaixo, a mesma conexão com o reconhecedor funciona sem um navegador: leia PCM de qualquer fonte, mantenha o ritmo da cadência de chunks em tempo real e receba os eventos. A chave de API e a URL vêm do ambiente, como no servidor.

// stream-stt.ts - pace ~100ms chunks at real time, then commit the tail.
const SAMPLE_RATE = 16000, CHUNK_MS = 100;
const CHUNK_BYTES = (SAMPLE_RATE * 2 * CHUNK_MS) / 1000; // 3200 bytes
const ws = new WebSocket(process.env.RECOGNIZER_WSS_URL!, {
  headers: { "xi-api-key": process.env.ELEVENLABS_API_KEY! },
});

// Send: walk the PCM buffer in 100ms chunks, sleeping between to mimic a
// live source. For audio that already arrives in real time, drop the sleep.
async function sendAudio(pcm: Buffer) {
  for (let off = 0; off < pcm.length; off += CHUNK_BYTES) {
    ws.send(pcm.subarray(off, off + CHUNK_BYTES));
    await new Promise((r) => setTimeout(r, CHUNK_MS));
  }
  ws.send(JSON.stringify({ type: "commit" })); // finalize the trailing segment
}

// Receive: print partials in place, append finals.
ws.on("message", (raw) => {
  const e = parseRecognizerEvent(raw.toString());
  if (e?.type === "final") console.log(`[final]   ${e.text}`);
  else if (e?.type === "partial") process.stdout.write(`[partial] ${e.text}\r`);
});

Benchmark de latência de transcrição de voz e taxa de erro de palavras

A latência e a taxa de erro de palavras variam de acordo com o locutor, o idioma, as condições acústicas, a duração do áudio, o caminho de rede até a região mais próxima de cada provedor e a carga atual de cada serviço. 

Um resultado medido em um laptop em uma cidade não se aplica automaticamente à sua infraestrutura de produção em outra. Execute o teste a partir de uma infraestrutura parecida com a de produção, usando áudio semelhante à sua entrada real, e informe faixas e distribuições em vez de números únicos.

Os únicos números de latência e precisão relevantes são os medidos em seu próprio áudio, a partir de uma infraestrutura semelhante à de produção. Veja um guia para fazer benchmark de latência de transcrição de voz.

O que medir na latência de transcrição de voz

Estas são as principais métricas que você deve medir ao avaliar a latência de transcrição de voz em tempo real:

  • Tempo até a primeira parcial: Do envio do primeiro chunk de áudio ao recebimento da primeira parcial não vazia.
  • Atraso entre parcial e final: Do último chunk de áudio de uma fala até a hipótese final.
  • Taxa de erro de palavras (WER): WER da transcrição finalizada em comparação com uma referência humana, calculada de forma idêntica em todos os sistemas.
  • Variação de estabilidade: Quantas parciais são reescritas antes da finalização. Essa medida indica o quanto a interface ao vivo parecerá mudar.

Controles

Para evitar dados pouco confiáveis, implemente vários controles no experimento para manter a consistência.

Estes são os principais controles para usar em benchmarks de latência de transcrição de voz:

  • Áudio idêntico: Use os mesmos arquivos, a mesma taxa de amostragem e a mesma codificação em todos os sistemas.
  • Cadência idêntica: Transmita para todos os sistemas na mesma cadência de chunks em tempo real, por exemplo, chunks de 100 ms.
  • Repita e informe distribuições: Execute cada arquivo muitas vezes ao longo do dia; informe a mediana e a cauda (p50/p95).
  • Referências e pontuação idênticas: Normalize o texto da mesma forma — maiúsculas, pontuação e números — antes de calcular a WER.
  • Informe a região e a rede: Indique onde o teste foi executado e o caminho até cada provedor.

Mantendo todos esses elementos iguais, você gerará métricas mais precisas.

Estrutura do teste

O núcleo de medição recebe um adaptador de provedor e registra o tempo até a primeira parcial, o atraso de finalização e as alterações das parciais:

// benchmark.ts - measurement core; one StreamFn adapter per provider.
type StreamFn = (
  audioPath: string,
  onEvent: (kind: "partial" | "final", text: string) => void,
  result: RunResult
) => Promise<void>; // adapter sets result.lastChunkSentAt on the final chunk

interface RunResult {
  firstPartialMs?: number;
  finalLagMs?: number;
  hypothesis: string;
  partialEdits: number;
  lastChunkSentAt: number;
  startedAt: number;
}

async function measure(streamFn: StreamFn, audioPath: string): Promise<RunResult> {
  const result: RunResult = {
    hypothesis: "", partialEdits: 0, lastChunkSentAt: 0,
    startedAt: performance.now(),
  };
  let prevPartial = "";

  await streamFn(audioPath, (kind, text) => {
    const now = performance.now();
    if (kind === "partial") {
      if (text && result.firstPartialMs === undefined)
        result.firstPartialMs = now - result.startedAt;
      if (text !== prevPartial) { result.partialEdits++; prevPartial = text; }
    } else { // final
      result.hypothesis = result.hypothesis ? `${result.hypothesis} ${text}` : text;
      if (result.lastChunkSentAt)
        result.finalLagMs = now - result.lastChunkSentAt;
    }
  }, result);

  return result;
}

A taxa de erro de palavras é uma distância de Levenshtein padrão no nível de tokens sobre texto normalizado. Converta para minúsculas e remova a pontuação da mesma forma na referência e na hipótese antes de calculá-la, ou você medirá seu normalizador, não o modelo. Execute essa medida em um loop que processe cada arquivo cerca de 10 vezes por provedor e informe a mediana do tempo até a primeira parcial e a WER mediana (p50/p95), pois uma única amostra é dominada pela variação da rede.

Para executar isso, você fornece duas coisas. Primeiro, escreva um adaptador StreamFn por sistema. O cliente programável acima já é um deles; os adaptadores para os outros seguem o mesmo contrato (audioPath, onEvent, result) e definem result.lastChunkSentAt quando o último chunk de áudio é enviado. Segundo, carregue seus arquivos de áudio e referências e chame as medições neles. Execute-o em uma máquina que represente sua implantação, com áudio que represente seus usuários, e você terá uma comparação reproduzível.

Resumo de como alcançar transcrição de voz em tempo real 

Abordamos muitas mudanças de arquitetura neste artigo, permitindo que você melhore seu sistema de forma iterativa e se aproxime da transcrição de voz em tempo real.

Um sistema STT em tempo real para produção se resume a algumas decisões:

  • Transporte: Escolha WebSocket para simplicidade e redes controladas, e WebRTC quando precisar de tolerância a perdas e estiver capturando de dispositivos de consumidores.
  • Parciais e finais: Trate parciais como provisórias e finais como confirmadas, e renderize-as de formas distintas para que os usuários confiem no texto ao vivo.
  • Detecção de fim de fala: Use VAD para segmentação sem uso das mãos, confirmação manual como substituição e ajuste o limite de silêncio à interação, em vez de usar uma constante.
  • Recursos no fluxo: Ative recursos no fluxo apenas quando a experiência ao vivo precisar deles e deixe o restante para um processamento em lote com o Scribe v2.
  • Formato de áudio: Capture em frames pequenos de PCM, envie chunks de cerca de 100 ms e corresponda ao formato da fonte para telefonia.
  • Benchmarking: Ajuste empiricamente os parâmetros de precisão versus latência usando seu próprio áudio e sua métrica-alvo.
  • Segurança da API: Mantenha sua chave de API no servidor ou gere tokens de uso único para conexões diretas do cliente.

Se quiser saber como otimizar a latência em um agente de voz, também escrevemos um guia para você.

Crie sistemas de transcrição de voz em tempo real com o Scribe v2 Realtime

O Scribe v2 Realtime produz parciais com cerca de 150 ms de latência do modelo. Seus usuários perceberão esse número ou algo maior dependendo da arquitetura ao redor dele — a parte que você controla. Ao usar as estratégias apresentadas neste artigo, você criará uma arquitetura de pipeline melhorada, que reduz a latência e aprimora a experiência do cliente. 

Para se aprofundar, conheça a visão geral dos recursos de Speech to Text, leia nossa referência de modelos para conferir a lista completa de recursos e idiomas e visite as páginas dos produtos em tempo real: API de Speech to Text em tempo real e Speech to Text em tempo real.

Quando estiver pronto para criar, crie uma conta gratuita na ElevenLabs e transmita sua primeira transcrição hoje.

Perguntas frequentes sobre latência de transcrição de voz em tempo real

Escrito por

Tadas Petra é engenheiro de Relações com Desenvolvedores e ajuda desenvolvedores a criar com a suíte de produtos da ElevenLabs. Ele também é fundador da Hungrimind, uma plataforma de educação para desenvolvedores. Antes disso, foi Líder de Advocacia para Desenvolvedores na Agora e instrutor na Zero To Mastery.

Artigos relacionados

Crie com o áudio de IA da mais alta qualidade