Introducing Eleven v4Introducing Eleven v4, our fastest and most emotive voice model

Ir al contenido

Voz a Texto en Tiempo Real en menos de 200 ms: Guía de arquitectura

Publicado
Última actualización

EscucharEscucha este artículo

La Voz a Texto (STT) en tiempo real transcribe activamente el audio mientras una persona habla y devuelve sus palabras en forma de texto en unos pocos cientos de milisegundos. Sin embargo, mantener baja la latencia de STT es tanto un problema de arquitectura como de modelo. Desarrolladores deben planificar el transporte, la fragmentación, la detección de final de intervención y la ruta de captura, ya que cada uno añade latencia a la ecuación. La ineficiencia en cualquiera de ellos puede agotar tu presupuesto de 200 ms.

Esta guía ofrece un sistema práctico que puedes usar para crear pipelines de Voz a Texto en tiempo real desde la capa de transporte. Nos centraremos en Scribe v2 Realtime, que genera transcripciones parciales con aproximadamente 150 ms de latencia de modelo, admite más de 90 idiomas, acepta audio PCM (8 kHz-48 kHz) y mu-law, e incluye Detección de Actividad de Voz y control de confirmación manual para finalizar segmentos.

Veremos cómo llega el audio al servidor, cómo evolucionan las hipótesis hasta convertirse en texto confirmado, qué coste tienen las funciones durante la transmisión y cómo capturar y reenviar audio correctamente.

Resumen

  • Crear sistemas de Voz a Texto en tiempo real requiere ajustar la arquitectura para mantener baja la latencia en todo el pipeline.
  • WebSocket es la opción predeterminada adecuada para la mayoría de pipelines, aunque WebRTC ofrece diversas ventajas a cambio de una mayor complejidad.
  • La Detección de Actividad de Voz se encarga de la segmentación manos libres, mientras que la confirmación manual permite a tus aplicaciones anularla cuando saben que la intervención ha terminado.
  • Los parciales son provisionales y los finales quedan confirmados, por lo que debes mostrarlos de forma distinta. 
  • Los fragmentos pequeños de PCM de unos 100 ms minimizan la latencia hasta el primer parcial.

WebSocket frente a WebRTC para Voz a Texto en tiempo real

Antes de que se produzca cualquier transcripción, el audio debe viajar desde la fuente hasta el reconocedor. El canal que elijas establece la latencia mínima de todo lo que viene después. Hay dos opciones viables para que el audio llegue a la capa de transcripción.

WebSocket es un canal bidireccional de larga duración, ordenado y fiable que funciona sobre TCP. Abres una conexión, envías fotogramas de audio binarios y recibes eventos de transcripción. Es sencillo tanto en el cliente como en el servidor, atraviesa los proxies corporativos y cortafuegos que ya permiten HTTPS, y todos los navegadores y entornos de servidor lo admiten. 

La limitación de WebSocket es que funciona sobre TCP. Si se pierde un paquete, TCP lo retransmite y retiene los datos posteriores hasta que se complete el hueco. En buenas condiciones de red, esto no se nota. Cuando hay pérdida de paquetes, produce bloqueo de cabecera de línea: una breve pausa en la que el audio se acumula y luego llega de golpe.

WebRTC está diseñado para medios en tiempo real. Transporta los medios mediante UDP (a través de SRTP), por lo que un paquete perdido no detiene el flujo; el pipeline continúa. Incluye un búfer de fluctuación que absorbe las variaciones en la llegada de paquetes, negocia el cruce de NAT con ICE/STUN/TURN para que puedan conectarse pares detrás de routers e incorpora sus propios mecanismos de captura y codificación de audio. 

Normalmente necesitas servidores TURN para clientes que no pueden conectarse directamente, y el lado del servidor debe terminar un flujo multimedia en lugar de leer un flujo de bytes.

Esta es la disyuntiva de un vistazo:

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 la mayoría de casos de uso, WebSocket es la opción adecuada. Úsalo cuando tus clientes tengan una conectividad aceptable y controles la ruta de captura: pipelines de servidor a servidor, aplicaciones de escritorio, aplicaciones de navegador con conexión de banda ancha y la mayoría de backends de centros de contacto en los que el audio ya llega a tu servidor por otro medio. 

Elige WebRTC cuando captures directamente desde dispositivos de consumo en redes móviles poco fiables, cuando ya ejecutes una infraestructura WebRTC para audio bidireccional —por ejemplo, un agente de voz que también responde hablando— o cuando el comportamiento en tiempo real con tolerancia a pérdidas importe más que la simplicidad de implementación.

El resto de esta guía usa transporte WebSocket para la conexión con el reconocedor, porque mantiene visibles los componentes y es el mejor punto de partida para la mayoría de equipos. Nada de esto es específico de WebSocket, por lo que más adelante puedes añadir una capa multimedia de WebRTC delante, decodificar el audio a PCM en el servidor y reenviar los mismos fragmentos al pipeline.

Parciales y transcripciones finales: explicación de los resultados provisionales

Un reconocedor en tiempo real no espera a tener una frase completa antes de generar texto. En su lugar, emite un flujo continuo de estimaciones que se afinan a medida que llega más audio y luego las confirma. Entender la diferencia entre estos dos estados separa una transcripción que parece viva de una que parece defectuosa. 

Una hipótesis parcial (provisional) es la mejor estimación del modelo con el audio recibido hasta el momento. Los parciales son inestables por diseño. A medida que llega más audio, el modelo revisa palabras anteriores: «Quiero» puede convertirse en «Quiero dos entradas» cuando el contexto posterior resuelve la ambigüedad. Llegan rápido —esto es lo que describe la cifra de latencia de unos 150 ms— y están pensados para sobrescribirse.

Una hipótesis final es un segmento confirmado que no cambiará. Una vez finalizado un segmento, el reconocedor continúa y las hipótesis posteriores describen audio posterior. Los finales son los que guardas, envías a un LLM o almacenas como transcripción.

La distinción entre parciales y finales determina tres aspectos que harás mal si los confundes:

  • Experiencia de usuario: Mostrar los parciales hace que una transcripción parezca en directo: el usuario ve cómo aparecen las palabras mientras habla, lo que confirma que el micrófono funciona y que el sistema está escuchando.
  • Detección de final de intervención: Los parciales te dan una señal continua de actividad de voz. Combinados con VAD, te permiten decidir cuándo la persona que habla se ha detenido realmente.
  • Sincronización posterior: En un pipeline de agente de voz los pasos son entrada de audio, después Voz a Texto, después un LLM, después Texto a Voz y, por último, salida de audio. Puedes empezar trabajo especulativo con los parciales y confirmarlo con los finales, reduciendo el tiempo de respuesta percibido a cambio de descartar ocasionalmente trabajo especulativo.

Muestra los parciales y los finales de forma distinta. Un patrón sencillo y eficaz consiste en mantener una única «línea actual» mutable vinculada al parcial más reciente y confirmarla en una transcripción a la que solo se añaden elementos cuando llega un 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, muestra el texto confirmado con un estilo normal y el actual con un estilo más claro o en cursiva para que el usuario entienda que aún puede cambiar.

Detección de final de intervención y detección de actividad de voz (VAD)

Saber qué se ha dicho es solo la mitad del trabajo. Un reconocedor también debe saber cuándo ha terminado una idea. Esa decisión determina cuándo finalizas un segmento y, en un agente, cuándo el sistema empieza a responder. 

La detección de final de intervención determina que una emisión ha terminado. Finalizar demasiado pronto interrumpe a usuarios a mitad de frase. Finalizar demasiado tarde deja a un agente en silencio después de que el usuario haya terminado claramente.

Scribe v2 Realtime ofrece dos mecanismos complementarios:

  • La Detección de Actividad de Voz segmenta el audio según el silencio: El reconocedor detecta cuándo la voz da paso a un silencio sostenido y usa ese límite para finalizar un segmento automáticamente. VAD es la opción predeterminada adecuada para interfaces conversacionales, porque se adapta al ritmo natural del habla sin que tengas que controlar los tiempos manualmente.
  • Control de confirmación manual: El control de confirmación manual permite a tu aplicación decidir cuándo finalizar el segmento actual, independientemente del silencio. Envías una señal de confirmación, el reconocedor cierra el segmento actual y emite un resultado final. Es la herramienta adecuada cuando tu aplicación ya sabe que la intervención ha terminado: al soltar un botón de pulsar para hablar, realizar una acción de «enviar» o aplicar una política externa de toma de turnos.

Ambos mecanismos se combinan bien. Un agente de voz típico usa VAD para funcionar sin manos y ofrece la confirmación manual como anulación, de modo que no interrumpe a un usuario que hace una pausa para pensar, pero proporciona un límite inmediato a quien pulsa un botón.

El umbral de silencio implica una disyuntiva real y no existe un valor universalmente correcto:

  • Un tiempo de espera corto para detectar el final de voz —por ejemplo, finalizar tras unos 200-400 ms de silencio— hace que el sistema parezca ágil. Sin embargo, también interrumpe a usuarios que hacen pausas naturales entre frases, divide una idea en varios segmentos y, en un agente, puede desencadenar una respuesta prematura.
  • Un tiempo de espera largo —por ejemplo, unos 800-1200 ms— tolera las pausas naturales y mantiene intactas las intervenciones, a costa de un retraso perceptible antes de que el sistema reaccione.

No hay una constante global que usar aquí; ajusta el umbral a la interacción:

  • El dictado y la toma de notas toleran pausas más largas porque usuarios piensan a mitad de frase. Prioriza tiempos de espera más largos y apóyate en VAD.
  • Los agentes de comandos y control, y los transaccionales, se benefician de tiempos de espera más cortos junto con la confirmación manual, porque las intervenciones son breves y precisas.
  • Quienes hablan varios idiomas o no son nativos hacen más pausas, así que reserva más silencio antes de finalizar.

Estos consejos te ayudarán a crear un sistema eficaz de detección de final de intervención y avanzar hacia la Voz a Texto en tiempo real.

Funciones durante la transmisión: detección de idioma y diarización de hablantes

El reconocimiento en streaming puede hacer más que generar palabras. Sin embargo, cada señal adicional que solicitas afecta a la latencia y la estabilidad. La regla general es activar solo lo que necesite la experiencia en directo y dejar el resto para un procesamiento por lotes.

El reconocimiento automático de idioma permite a Scribe v2 Realtime identificar el idioma hablado entre sus más de 90 idiomas compatibles, sin que tengas que indicarlo de antemano. El coste es que el modelo necesita un breve fragmento de audio para determinarlo con seguridad, por lo que los primeros parciales de una transmisión pueden ser menos estables mientras se establece el idioma. Si ya conoces el idioma, especificarlo elimina esa ambigüedad y suele generar parciales iniciales más estables.

Diarización de hablantes atribuye el habla a distintas personas e identifica quién dijo qué. En la transcripción por lotes, esto es comparativamente sencillo porque el modelo ve todo el archivo. En streaming es más difícil: el reconocedor debe asignar una etiqueta de hablante únicamente con el audio recibido hasta entonces, y una etiqueta asignada al audio inicial puede requerir revisión cuando se escucha más de la voz de ese hablante. Trata las etiquetas de hablante en streaming igual que el texto parcial: como provisionales hasta que el segmento se finalice.

Las marcas de tiempo por palabra y el contexto de entidades siguen la misma lógica. Cuantos más metadatos por token solicites, más tendrán que transportar tanto el modelo como la conexión. Para la mayoría de interfaces en tiempo real, necesitas el texto y los límites de segmento en directo, y nada más; puedes dejar los metadatos detallados para un procesamiento por lotes posterior a la llamada con Scribe v2.

Formatos de audio para streaming: PCM y mu-law

La lógica de transporte y reconocimiento recibe la mayor parte de la atención, pero una proporción sorprendente de errores reales se origina un nivel más abajo: en cómo codificas y fragmentas el audio. Elegir bien el formato y el tamaño de fragmento es la mejora más económica disponible para reducir la latencia de Voz a Texto.

PCM —lineal, con signo de 16 bits y little-endian— es el formato que debes usar cuando controles la captura. Las frecuencias de muestreo más altas contienen más detalle acústico: 16 kHz es el mínimo estándar para el reconocimiento de voz y suele ser suficiente; 8 kHz tiene calidad telefónica y pierde contenido de alta frecuencia. Usa la frecuencia que corresponda a tu fuente. No tiene sentido aumentar la frecuencia del audio de telefonía de 8 kHz a 48 kHz, porque no hay información que recuperar.

Mu-law a 8 kHz es el formato de telefonía. Si recibes llamadas de un proveedor como Twilio, el audio llega como mu-law a 8 kHz y debes reenviarlo en ese formato en lugar de transcodificarlo dos veces. Ajustarse al formato de origen evita artefactos de remuestreo y un paso de conversión innecesario.

El tamaño de los fragmentos es la palanca que más directamente determina la latencia percibida. Envías audio en fragmentos y el reconocedor genera parciales a medida que llegan. Los fragmentos más pequeños implican actualizaciones más frecuentes y menos latencia hasta el primer parcial; los más grandes implican menos mensajes y un poco más de contexto por inferencia. Un rango práctico es de 20 a 250 ms de audio por fragmento. Como referencia concreta, con PCM mono de 16 bits a 16 kHz, un segundo de audio ocupa 32.000 bytes, por lo que un fragmento de 100 ms ocupa unos 3.200 bytes.

Capturar la entrada del micrófono en el navegador

En el navegador, la herramienta adecuada es la Audio API web con un AudioWorklet. El worklet se ejecuta en el hilo de renderizado de audio, recibe audio en fotogramas pequeños y no sufre los bloqueos del hilo principal que afectaban al antiguo ScriptProcessorNode. Su función es convertir las muestras nativas de coma flotante del navegador a PCM de 16 bits y entregarlas al hilo principal, que las reenvía mediante WebSocket.

El núcleo del procesador worklet es la conversión de coma flotante a 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);

El pipeline en código

El pipeline tiene tres componentes: un cliente de navegador que captura el micrófono y transmite PCM a tu servidor, un servidor Node que reenvía el audio a Scribe v2 Realtime y devuelve las transcripciones, y un cliente programable que transmite PCM desde un archivo o una pasarela de telefonía.

El servidor actúa como intermediario en lugar de exponer el reconocedor directamente al navegador por una razón importante: tu clave de API de ElevenLabs es secreta y nunca debe aparecer en código del lado del cliente. El servidor guarda la clave. Si necesitas que el navegador se comunique directamente con el reconocedor, genera en el servidor un token de un solo uso y corta duración y entrega ese token al cliente en lugar de la clave de API.

Cliente de navegador

El cliente abre un WebSocket con tu servidor, captura el micrófono mediante el worklet anterior y reenvía cada fotograma PCM en cuanto se genera. Los eventos entrantes —ya normalizados por el servidor con la estructura { type, text }— controlan el estado parcial/final explicado antes:

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

Servidor intermediario

El servidor abre una conexión con el reconocedor por cliente, mantiene la clave de API en el servidor, reenvía directamente el PCM binario y normaliza los eventos del reconocedor a la estructura estable { type, text } que consume el 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
});

Todo lo específico de la ruta de API queda limitado a las dos funciones de adaptación siguientes. Sustituye los nombres de campo por los exactos de la referencia de Voz a Texto; el resto del pipeline no cambia:

// 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 backend programable

Para pipelines de backend y para la prueba comparativa siguiente, la misma conexión con el reconocedor funciona sin navegador: lee PCM de cualquier fuente, envíalo al ritmo de fragmentos en tiempo real y recibe los eventos. La clave de API y la URL proceden del entorno, igual que en el 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`);
});

Pruebas comparativas de latencia de Voz a Texto y tasa de error por palabra

Tanto la latencia como la tasa de error por palabra varían según la persona que habla, el idioma, las condiciones acústicas, la duración del audio, la ruta de red hasta la región más cercana de cada proveedor y la carga actual de cada servicio. 

Un resultado medido desde un portátil en una ciudad no se puede generalizar a tu infraestructura de producción en otra. Ejecuta el entorno de prueba desde una infraestructura similar a producción, con audio parecido a tu entrada real, e informa de rangos y distribuciones en lugar de cifras únicas.

Las únicas cifras de latencia y precisión que importan son las que mides con tu propio audio desde una infraestructura similar a producción. Esta es una guía para hacer pruebas comparativas de latencia de Voz a Texto.

Qué medir para la latencia de Voz a Texto

A continuación tienes las principales métricas que debes medir al evaluar la latencia de Voz a Texto en tiempo real:

  • Tiempo hasta el primer parcial: Desde el envío del primer fragmento de audio hasta la recepción del primer parcial no vacío.
  • Retraso de parcial a final: Desde el último fragmento de audio de una intervención hasta la hipótesis final.
  • Tasa de error por palabra (WER): WER de la transcripción finalizada frente a una referencia humana, calculada de forma idéntica en todos los sistemas.
  • Cambios de estabilidad: Cuántos parciales se reescriben antes de finalizar. Esta medida indica cuánto parecerá cambiar la interfaz en directo.

Controles

Para evitar datos poco fiables, debes implementar varios controles en tu experimento para mantener la coherencia.

Estos son los principales controles para las pruebas comparativas de latencia de Voz a Texto:

  • Audio idéntico: Usa los mismos archivos, la misma frecuencia de muestreo y la misma codificación en todos los sistemas.
  • Ritmo idéntico: Transmite todos los sistemas con la misma cadencia de fragmentos en tiempo real —por ejemplo, fragmentos de 100 ms—.
  • Repite e informa de las distribuciones: Ejecuta cada archivo muchas veces a lo largo del día; informa de la mediana y la cola (p50/p95).
  • Referencias y evaluación idénticas: Normaliza el texto del mismo modo —mayúsculas, puntuación y números— antes de calcular WER.
  • Indica la región y la red: Especifica dónde se ejecutó el entorno de prueba y la ruta hasta cada proveedor.

Al mantener todos estos elementos iguales, generarás métricas más precisas.

Estructura básica del entorno de prueba

El núcleo de medición recibe un adaptador de proveedor y registra el tiempo hasta el primer parcial, el retraso de finalización y los cambios en los parciales:

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

La tasa de error por palabra es una distancia de Levenshtein estándar a nivel de token sobre texto normalizado. Convierte a minúsculas y elimina la puntuación de forma idéntica tanto en la referencia como en la hipótesis antes de calcularla, o medirás tu normalizador en lugar del modelo. Incluye esta medida en un bucle que ejecute cada archivo unas 10 veces por proveedor e informe de la mediana del tiempo hasta el primer parcial y de la WER mediana (p50/p95), ya que una sola muestra está dominada por la variación de la red.

Para ejecutarlo, necesitas proporcionar dos elementos. Primero, escribe un adaptador StreamFn por sistema. El cliente programable anterior ya es uno; los adaptadores para los demás siguen el mismo contrato (audioPath, onEvent, result) y establecen result.lastChunkSentAt cuando se envía el último fragmento de audio. Segundo, carga tus archivos de audio y referencias, y llama a las mediciones para todos ellos. Ejecútalo desde una máquina representativa de tu despliegue, con audio representativo de tus usuarios, y tendrás una comparación reproducible.

Resumen para lograr Voz a Texto en tiempo real 

Hemos visto muchos cambios arquitectónicos en este artículo que te permiten mejorar tu sistema de forma iterativa y avanzar hacia la Voz a Texto en tiempo real.

Un sistema de STT en tiempo real para producción se reduce a unas pocas decisiones:

  • Transporte: Elige WebSocket por su simplicidad y para redes controladas, y WebRTC cuando necesites tolerancia a pérdidas y captures desde dispositivos de consumo.
  • Parciales y finales: Trata los parciales como provisionales y los finales como confirmados, y muéstralos de forma distinta para que usuarios confíen en el texto en directo.
  • Detección de final de intervención: Usa VAD para la segmentación manos libres, la confirmación manual como anulación y ajusta el umbral de silencio a la interacción en lugar de usar una constante.
  • Funciones durante la transmisión: Activa las funciones durante la transmisión solo cuando las necesite la experiencia en directo y deja el resto para un procesamiento por lotes con Scribe v2.
  • Formato de audio: Captura en fotogramas PCM pequeños, envía fragmentos de unos 100 ms y ajusta el formato a la fuente para telefonía.
  • Pruebas comparativas: Ajusta empíricamente los parámetros de precisión frente a latencia usando tu propio audio y la métrica objetivo.
  • Seguridad de la API: Mantén tu clave de API en el servidor o genera tokens de un solo uso para conexiones directas de clientes.

Si quieres ver cómo optimizar la latencia en un agente de voz, también hemos preparado una guía para ti.

Crea sistemas de Voz a Texto en tiempo real con Scribe v2 Realtime

Scribe v2 Realtime genera parciales con aproximadamente 150 ms de latencia de modelo. Que tus usuarios perciban esa cifra u otra mayor depende de la arquitectura que la rodea, que es la parte que controlas. Al aplicar las estrategias de este artículo, crearás una arquitectura de pipeline mejorada que reduce la latencia y mejora la experiencia del cliente. 

Para profundizar, descubre la descripción general de las capacidades de Voz a Texto, consulta nuestra referencia de modelos para ver la lista completa de funciones e idiomas y visita las páginas de producto en tiempo real: API de Voz a Texto en tiempo real y Voz a Texto en tiempo real.

Cuando estés listo para crear, crea una cuenta gratuita de ElevenLabs y transmite hoy tu primera transcripción.

Preguntas frecuentes sobre la latencia de Voz a Texto en tiempo real

Artículos relacionados

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