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

O Speech to Text (STT) em tempo real transcreve o áudio enquanto a pessoa fala, retornando o texto em poucos milissegundos. Mas manter a latência do STT baixa é tanto um desafio de arquitetura quanto de modelo. Os engenheiros precisam planejar o transporte, divisão em blocos, detecção de fim de fala e captura, já que cada etapa adiciona latência. Qualquer ineficiência pode estourar o limite de 200ms.

Este guia traz um sistema prático para você construir fluxos de Speech to Text em tempo real, começando pela camada de transporte. Vamos focar no Scribe v2 Tempo Real, que gera transcrições parciais em cerca de 150ms de latência do modelo, suporta mais de 90 idiomas, aceita áudio PCM (8kHz-48kHz) e mu-law, e oferece Detecção de Atividade de Voz (VAD) além do controle manual de finalização de segmentos.

Vamos mostrar como o áudio chega ao servidor, como as hipóteses evoluem até virar texto final, o custo dos recursos em tempo real e como capturar e encaminhar o áudio corretamente.

Resumo rápido

  • Criar sistemas de Speech to Text em tempo real exige ajustes finos na arquitetura para garantir latência baixa em todo o fluxo.
  • WebSocket é a melhor escolha para a maioria dos fluxos, embora o WebRTC ofereça vantagens, sendo mais complexo.
  • A Detecção de Atividade de Voz faz a segmentação automática, e o commit manual permite que seu app finalize quando souber que a fala terminou.
  • Transcrições parciais são provisórias e finais são definitivas, então você deve exibi-las de formas diferentes.
  • Blocos pequenos de PCM, em torno de 100ms, reduzem a latência até a primeira parcial.

WebSocket vs. WebRTC para Speech to Text em tempo real

Antes de qualquer transcrição, o áudio precisa ir da fonte até o reconhecedor. O canal escolhido define a latência mínima do fluxo. Existem duas opções viáveis para o áudio chegar à camada de transcrição.

WebSocket é um canal duradouro, ordenado, confiável e bidirecional sobre TCP. Você abre a conexão, envia quadros de áudio binários e recebe eventos de transcrição. É simples tanto no cliente quanto no servidor, atravessa proxies e firewalls corporativos que já permitem HTTPS, e é suportado por todos os navegadores e servidores.

A limitação do WebSocket é que ele usa TCP. Se um pacote se perde, o TCP retransmite e segura os dados seguintes até preencher a lacuna. Em redes boas, isso não é perceptível. Com perda de pacotes, pode ocorrer um atraso, acumulando áudio e depois enviando tudo de uma vez.

WebRTC foi criado para mídia em tempo real. Ele usa UDP (via SRTP), então a perda de pacotes não trava o fluxo; o áudio continua. Inclui buffer de jitter para absorver variações na chegada dos pacotes, negocia NAT com ICE/STUN/TURN para conectar dispositivos atrás de roteadores e traz sua própria captura e codificação de áudio.

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

Veja o resumo da comparação:

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, WebSocket é a melhor opção. Use quando seus clientes têm boa conexão e você controla a captura: fluxos servidor-servidor, apps desktop, apps web em banda larga e backends de contact center onde o áudio já chega ao seu servidor.

Escolha WebRTC quando estiver capturando direto de dispositivos em redes móveis instáveis, quando já usa WebRTC para áudio bidirecional (como um agente de voz que também responde) ou quando a tolerância a perdas é mais importante que a simplicidade.

O restante deste guia usa WebSocket para conectar ao reconhecedor, pois deixa tudo mais visível e é o ponto de partida ideal para a maioria das equipes. Nada é exclusivo do WebSocket, então você pode adicionar WebRTC na frente, decodificar o áudio para PCM no servidor e encaminhar os blocos normalmente.

Parciais e finais: como funcionam os resultados intermediários

Um reorganizador em tempo real não espera a frase completa para responder. Ele envia uma sequência de hipóteses que vão se ajustando conforme chega mais áudio, até fixar o resultado. Entender a diferença entre esses dois estados é o que faz uma transcrição parecer viva, e não quebrada.

Uma hipótese parcial é o melhor palpite do modelo com o áudio recebido até o momento. Parciais são instáveis por natureza. Com mais áudio, o modelo pode revisar palavras anteriores: "Eu quero" pode virar "Eu quero dois ingressos" quando o contexto fica claro. Elas chegam rápido (é disso que falamos ao citar ~150ms de latência) e devem ser sobrescritas.

Uma hipótese final é um segmento definitivo que não muda mais. Depois de finalizar um segmento, o reconhecedor segue em frente e as próximas hipóteses tratam do áudio seguinte. Os finais são os que você salva, envia para um LLM ou armazena como transcrição.

A diferença entre parciais e finais impacta três pontos que podem dar errado se você misturar os conceitos:

  • Experiência do usuário: Mostrar parciais faz a transcrição parecer ao vivo: o usuário vê as palavras surgindo enquanto fala, confirmando que o microfone está funcionando e o sistema está ouvindo.
  • Finalização: Parciais dão um sinal contínuo de atividade de fala. Combinadas com VAD, permitem decidir quando o usuário realmente parou de falar.
  • Tempo de resposta: Em um fluxo de agente de voz as etapas são: áudio entra, depois Speech to Text, depois LLM, depois Transformar Texto em Áudio, depois áudio sai. Você pode começar a processar com base nas parciais e confirmar com os finais, reduzindo o tempo de resposta percebido, mesmo que às vezes precise descartar o trabalho especulativo.

Exiba parciais e finais de formas diferentes. Um padrão simples e eficiente é manter uma "linha atual" mutável com a última parcial e adicioná-la à transcrição quando chegar o final:

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, mostre o texto final como fixo e o atual em um estilo mais claro ou itálico, para o usuário entender que ainda pode mudar.

Finalização e detecção de atividade de voz (VAD)

Saber o que foi dito é só metade do desafio. O reconhecedor também precisa saber quando o pensamento terminou. Essa decisão define quando finalizar um segmento e, em um agente, quando o sistema começa a responder.

Finalização é decidir que a fala terminou. Finalizar cedo demais corta o usuário no meio da frase. Finalizar tarde demais deixa o agente em silêncio depois que o usuário já terminou.

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 ao silêncio e usa esse limite para finalizar o segmento automaticamente. VAD é o padrão ideal para interfaces conversacionais, pois se adapta ao ritmo natural da fala sem precisar controlar o tempo manualmente.
  • Commit manual: O commit manual permite que seu app decida quando finalizar o segmento atual, independente do silêncio. Você envia um sinal de commit, o reconhecedor fecha o segmento e emite o final. Isso é útil quando seu app já sabe que a vez acabou: ao soltar o botão de fala, ao clicar em "enviar" ou seguindo uma política externa de turnos.

Os dois funcionam bem juntos. Um agente de voz típico usa VAD para operação sem as mãos e oferece commit manual como alternativa, assim o usuário que pausa para pensar não é cortado, mas quem aperta um botão tem o segmento finalizado na hora.

O limite de silêncio é um ajuste real, sem valor universal:

  • Um tempo curto de silêncio (por exemplo, finalizar após ~200-400ms) faz o sistema parecer ágil. Mas pode cortar usuários que pausam naturalmente, dividindo um pensamento em vários segmentos e, em um agente, gerando respostas prematuras.
  • Um tempo longo (por exemplo, ~800-1200ms) tolera pausas naturais e mantém frases inteiras, mas gera um atraso perceptível antes da resposta.

Não existe um valor fixo ideal; ajuste o limite conforme a interação:

  • Ditado e anotações toleram pausas maiores, pois o usuário pensa enquanto fala. Prefira limites mais longos e use VAD.
  • Comandos e agentes transacionais se beneficiam de limites curtos e commit manual, pois as falas são rápidas e objetivas.
  • Falantes multilíngues ou não nativos pausam mais, então aumente o tempo de silêncio antes de finalizar.

Seguindo essas dicas, você constrói um sistema de finalização eficiente e avança para Speech to Text em tempo real.

Recursos em tempo real: detecção de idioma e diarização de falantes

O reconhecimento em streaming pode fazer mais do que gerar palavras. Mas cada recurso extra impacta latência e estabilidade. A regra é ativar só o que a experiência ao vivo precisa e deixar o resto para processamento em lote.

O reconhecimento automático de idioma permite que o Scribe v2 Realtime identifique o idioma falado entre mais de 90 suportados, sem exigir que você defina antes. O modelo precisa de um trecho curto de áudio para decidir com confiança, então as primeiras parciais podem ser menos estáveis enquanto o idioma é definido. Se você já sabe o idioma, informar isso evita ambiguidades e deixa as parciais iniciais mais estáveis.

A diarização de falantes atribui a fala a diferentes pessoas, identificando quem disse o quê. Em transcrição em lote, isso é mais fácil porque o modelo vê o arquivo inteiro. No streaming, é mais difícil: o reconhecedor precisa rotular o falante só com o áudio recebido até então, e pode precisar revisar o rótulo conforme ouve mais. Trate os rótulos de falante em streaming como as parciais: provisórios até o segmento ser finalizado.

Tempo por palavra e contexto de entidades seguem a mesma lógica. Quanto mais metadados por token você pedir, mais o modelo e a rede precisam carregar. Para a maioria das interfaces ao vivo, basta o texto e os limites dos segmentos; os metadados detalhados podem ser processados depois, em lote, com o Scribe v2.

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

O transporte e a lógica de reconhecimento recebem muita atenção, mas muitos bugs reais vêm de um nível abaixo: como você codifica e divide o áudio. Acertar o formato e o tamanho dos blocos é o jeito mais fácil de reduzir a latência do Speech to Text.

PCM (linear, 16 bits, little-endian) é o formato ideal quando você controla a captura. Taxas de amostragem maiores trazem mais detalhes: 16kHz é o mínimo para reconhecimento de fala e costuma ser suficiente; 8kHz é padrão telefônico e perde frequências altas. Use a taxa que corresponde à sua fonte. Não adianta aumentar de 8kHz para 48kHz, pois a informação não existe para recuperar.

Mu-law em 8kHz é o formato telefônico. Se você recebe ligações de um provedor como Twilio, o áudio chega em 8kHz mu-law e deve ser encaminhado assim, sem transcodificar duas vezes. Manter o formato original evita artefatos e conversões desnecessárias.

O tamanho dos blocos é o que mais impacta a latência percebida. Você envia o áudio em blocos, e o reconhecedor gera parciais conforme eles chegam. Blocos menores trazem atualizações mais frequentes e menor latência até a primeira parcial; blocos maiores reduzem mensagens e dão mais contexto por inferência. O ideal é de 20 a 250ms por bloco. Por exemplo, em PCM mono 16kHz 16 bits, um segundo de áudio tem 32.000 bytes, então um bloco de 100ms tem cerca de 3.200 bytes.

Capturando áudio do microfone no navegador

No navegador, a melhor ferramenta é a Web Audio API com um AudioWorklet. O worklet roda na thread de áudio, recebe quadros pequenos e não sofre com travamentos da thread principal como o antigo ScriptProcessorNode. Ele converte os samples float do navegador para PCM 16 bits e envia para a thread principal, que 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 partes: um cliente web que captura o microfone e envia PCM para seu servidor, um servidor Node que repassa o áudio para o Scribe v2 Realtime e devolve as transcrições, e um cliente scriptável que transmite PCM de um arquivo ou ponte telefônica.

O servidor faz o repasse em vez de expor o reconhecedor direto ao navegador por um motivo importante: sua chave de API da ElevenLabs é secreta e nunca deve aparecer no código do cliente. O servidor guarda a chave. Se precisar que o navegador fale direto com o reconhecedor, gere um token temporário no servidor e entregue ao cliente, nunca a chave da API.

Cliente web

O cliente abre um WebSocket para seu servidor, captura o microfone com o worklet acima e encaminha cada quadro PCM assim que é gerado. Os eventos recebidos (já normalizados pelo servidor em { type, text }) controlam o estado parcial/final:

// 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" }));

Repasse do servidor

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

// 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. Troque os nomes dos campos pelos exatos da referência do Speech to Text; o resto 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 backend scriptável

Para fluxos backend e para o benchmark abaixo, a mesma conexão com o reconhecedor funciona sem navegador: leia PCM de qualquer fonte, envie no ritmo real dos blocos e leia os eventos de volta. 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`);
});

Benchmarking de latência e taxa de erro de palavras no Speech to Text

Latência e taxa de erro de palavras variam conforme o falante, idioma, condições acústicas, duração do áudio, caminho de rede até a região mais próxima do provedor e carga atual do serviço.

Um resultado medido em um notebook de uma cidade não vale para sua operação em outra. Rode o teste em infraestrutura parecida com a produção, com áudio semelhante ao real, e reporte faixas e distribuições, não só números únicos.

Os únicos números de latência e precisão que importam são os que você mede com seu próprio áudio em infraestrutura parecida com a produção. Veja como fazer benchmarking de latência em Speech to Text.

O que medir na latência do Speech to Text

Veja as principais métricas para medir ao testar a latência do Speech to Text em tempo real:

  • Tempo até a primeira parcial: Do envio do primeiro bloco de áudio até receber a primeira parcial não vazia.
  • Atraso da parcial ao final: Do último bloco de áudio de uma fala até a hipótese final.
  • Taxa de erro de palavras (WER): WER na transcrição final comparada a uma referência humana, calculada igual em todos os sistemas.
  • Instabilidade das parciais: Quantas parciais são reescritas antes de finalizar. Isso indica o quanto a interface ao vivo vai parecer mudar.

Controles

Para evitar dados inconsistentes, implemente alguns controles no experimento para manter tudo igual.

Veja os principais controles para usar no benchmarking de latência do Speech to Text:

  • Áudio idêntico: Use os mesmos arquivos, mesma taxa de amostragem e mesma codificação para todos os sistemas.
  • Ritmo idêntico: Transmita todos os sistemas no mesmo ritmo de blocos (por exemplo, blocos de 100ms).
  • Repita e reporte distribuições: Rode cada arquivo várias vezes ao longo do dia; reporte mediana e extremos (p50/p95).
  • Referências e avaliação idênticas: Normalize o texto igual (caixa, pontuação, números) antes de calcular o WER.
  • Informe região e rede: Diga onde o teste foi rodado e o caminho até cada provedor.

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

Estrutura do teste

O núcleo da medição recebe um adaptador de provedor e registra tempo até a primeira parcial, atraso de finalização e instabilidade 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 é a distância de Levenshtein por token sobre texto normalizado. Coloque tudo em minúsculas e remova pontuação igual na referência e na hipótese antes de calcular, senão você mede o normalizador e não o modelo. Rode cada arquivo cerca de 10 vezes por provedor e reporte a mediana do tempo até a primeira parcial e do WER (p50/p95), já que uma amostra só é afetada pela variação de rede.

Para rodar, você precisa de duas coisas. Primeiro, escreva um adaptador StreamFn por sistema. O cliente scriptável acima já é um, e os adaptadores dos outros seguem o mesmo contrato (audioPath, onEvent, result), marcando result.lastChunkSentAt quando o último bloco de áudio for enviado. Depois, carregue seus arquivos de áudio e referências e chame as medições. Rode em uma máquina que represente seu ambiente de produção, com áudio realista, para ter uma comparação reproduzível.

Resumo: como alcançar Speech to Text em tempo real

Vimos várias mudanças de arquitetura neste artigo, permitindo que você melhore seu sistema e avance para Speech to Text em tempo real.

Um sistema de STT em tempo real para produção depende de algumas decisões:

  • Transporte: Escolha WebSocket pela simplicidade e redes controladas, e WebRTC quando precisar de tolerância a perdas e capturar de dispositivos de usuários.
  • Parciais e finais: Trate parciais como provisórias e finais como definitivas, exibindo de formas diferentes para o usuário confiar no texto ao vivo.
  • Finalização: Use VAD para segmentação automática, commit manual como alternativa e ajuste o limite de silêncio conforme a interação, não como valor fixo.
  • Recursos em tempo real: Ative recursos em tempo real só quando a experiência ao vivo exigir, e deixe o resto para processamento em lote com o Scribe v2.
  • Formato de áudio: Capture em blocos pequenos de PCM, envie blocos de ~100ms e mantenha o formato original para telefonia.
  • Benchmarking: Ajuste precisão e latência na prática, usando seu próprio áudio e 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 ver como otimizar a latência em um agente de voz, também temos um guia para você.

Construa sistemas de Speech to Text em tempo real com o Scribe v2 Realtime

O Scribe v2 Realtime gera parciais em cerca de 150ms de latência do modelo. Se seus usuários vão sentir esse número ou algo maior depende da arquitetura ao redor, que é onde você tem controle. Usando as estratégias deste artigo, você constrói um fluxo mais eficiente, reduz a latência e melhora a experiência do cliente.

Para se aprofundar, confira a visão geral das capacidades do Speech to Text, leia nossa referência de modelos para ver todos os 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 quiser começar, crie uma conta gratuita na ElevenLabs e faça sua primeira transcrição hoje mesmo.

Perguntas frequentes sobre latência em Speech to Text em tempo real

Artigos relacionados

Crie com o áudio de IA da mais alta qualidade