El problema de WebRTC en OpenAI
(moq.dev)- WebRTC prioriza la baja latencia, como en las llamadas de conferencia, por lo que cuando la red va mal descarta agresivamente paquetes de audio; pero en Voice AI, el deterioro del prompt de voz puede perjudicar más la calidad de la respuesta que una respuesta lenta
- TTS puede generar audio más rápido que en tiempo real, así que el buffering del cliente puede ocultar interrupciones breves de red; pero con WebRTC hay que esperar artificialmente para enviar los paquetes a tiempo por el renderizado según la hora de llegada y su pequeño búfer de jitter
- WebRTC complica la configuración y operación de conexiones con puertos efímeros, ICE, DTLS y SCTP; en la multiplexación por un solo puerto también es difícil enrutar paquetes STUN, SRTP/SRTCP, DTLS y TURN a cada conexión
- Aunque OpenAI exija una conexión rápida, con WebRTC la combinación de señalización y procedimientos del servidor de medios puede requerir al menos 8 RTT; y por su estructura orientada a P2P, aunque el servidor tenga IP fija debe pasar por el mismo proceso
- Como alternativas se proponen WebSockets y QUIC/WebTransport; QUIC, mediante
CONNECTION_ID, QUIC-LB ypreferred_address, soporta de forma más simple puerto único, cambios de dirección, balanceo sin estado y combinaciones de anycast con unicast
Por qué WebRTC no encaja con Voice AI
- WebRTC fue diseñado para conversaciones de ida y vuelta rápidas, como las llamadas de conferencia, así que cuando la red está en mal estado descarta agresivamente paquetes de audio para mantener baja la latencia
- En Voice AI, aunque el usuario espere un poco más una respuesta lenta, es más importante que el prompt se transmita con precisión
- Por ejemplo, si se daña un prompt de voz como “ir caminando al autolavado o ir manejando”, la calidad de la respuesta posterior también puede empeorar
- La implementación de audio de WebRTC en el navegador asume fuertemente la latencia en tiempo real, y dicen que cuando lo intentaron en Discord no fue posible retransmitir paquetes de audio de WebRTC
- En una actualización, algunas personas vinculadas a WebRTC consideraron que quizá sí era posible activar NACK para audio, pero en Discord no encontraron la forma correcta de manipular SDP, y además sigue existiendo la limitación de que el búfer de jitter de WebRTC es muy pequeño
- Incluso si algún día los agentes de Voice AI alcanzan latencias a nivel de conversación, reducir la latencia implica trade-offs, y no está claro si vale la pena elegir degradar intencionalmente los prompts de voz
El problema del buffering entre TTS y WebRTC
- La conversión de texto a voz (TTS) puede generar audio más rápido que en tiempo real
- Por ejemplo, si una GPU genera 8 segundos de audio en 2 segundos, idealmente durante esos 2 segundos se podría ir transmitiendo el audio generado mientras el cliente lo reproduce durante 8 segundos y asegura un búfer local
- Así, aunque haya una interrupción breve de red, es posible que el usuario ni la note
- WebRTC no encaja con este enfoque
- WebRTC no tiene buffering y renderiza según la hora de llegada, y considera que las marcas de tiempo no son una referencia fuerte de reproducción
- Si además se incluye video, el problema se vuelve más complicado
- Servicios como OpenAI tienen que esperar artificialmente antes de enviar cada paquete de audio, para que llegue justo en el momento en que debe reproducirse
- Si aparece congestión en la red, ese paquete de audio se pierde y no se retransmite
- El resultado es una estructura que primero introduce latencia artificial y luego descarta agresivamente paquetes para lograr “baja latencia”, algo parecido a mostrar un video de YouTube por screen sharing sin buffering
- WebRTC usa para audio un búfer de jitter ajustable dinámicamente entre 20 ms y 200 ms; esto sirve para mitigar el jitter de red, pero aquí se considera innecesario si se puede transmitir más rápido que en tiempo real
Limitaciones de los puertos y de la identificación de conexiones
- Un servidor TCP normalmente abre un puerto como
443y acepta conexiones, que se identifican por la combinación de IP y puerto de origen/destino- Ejemplo:
123.45.67.89:54321 -> 192.168.1.2:443
- Ejemplo:
- Si un teléfono cambia de Wi‑Fi a red celular o si un NAT modifica la IP/puerto de origen, la conexión TCP se corta y hay que crear una nueva
- El handshake de TCP y TLS requiere al menos 2~3 RTT, y en live streaming el usuario puede notar la interrupción de red
- Para resolver este problema, WebRTC asume un esquema donde se asigna un puerto de destino efímero a cada conexión
- Si la sesión se identifica solo por IP/puerto de destino, aunque cambie la IP/puerto de origen se puede seguir reconociendo al mismo usuario
- Pero, combinado con la arquitectura de OpenAI, este enfoque genera problemas a gran escala
- Hay un límite en la cantidad de puertos que el servidor puede usar
- Los firewalls suelen bloquear puertos efímeros
- Tampoco encaja bien con entornos Kubernetes
Por qué los servicios WebRTC terminan usando multiplexación en un solo puerto
- Muchos servicios no siguen la especificación de WebRTC al pie de la letra y multiplexan varias conexiones en un solo puerto
- En Twitch, los servidores WebRTC operaban en
UDP:443- Aunque
443es originalmente un puerto de HTTPS/QUIC, esto permitía atravesar más firewalls - Se dice que la red interna de Amazon solo permitía unos 30 puertos
- Aunque
- Discord usa los puertos
50000-50032, uno por cada núcleo de CPU- Este método puede quedar bloqueado en más redes internas
- El gran problema de la multiplexación en un solo puerto es que WebRTC es una estructura que agrupa varios estándares
- Hay 5 protocolos que corren directamente sobre UDP; distinguir de qué protocolo es un paquete no es tan difícil, pero sí lo es decidir a qué conexión debe enrutarse cada paquete
-
Dificultades de enrutamiento por protocolo
- STUN
- Se puede elegir un
ufragúnico y enrutar con base en él
- Se puede elegir un
- SRTP/SRTCP
- El navegador elige un valor
ssrcarbitrario, y normalmente se puede enrutar a partir de él
- El navegador elige un valor
- DTLS
- Hay que asumir un soporte amplio de RFC9146
- TURN
- Se aclara que no hay experiencia de implementación
- OpenAI explicó que solo parsea STUN y después trata DTLS, RTP y RTCP de forma opaca usando estado en caché
- Esto se interpreta como una estructura que espera que la IP/puerto de origen del usuario no cambie
- El navegador también podría generar al azar el mismo
ssrc - Si ocurre una colisión y no hay mapeo de IP/puerto de origen, en Discord identifican la conexión intentando descifrar el paquete con cada clave posible hasta encontrar la correcta
- STUN
La latencia de ida y vuelta al establecer conexiones WebRTC
- OpenAI presentó como uno de sus requisitos una “configuración rápida de la conexión para que el usuario pueda hablar apenas comience la sesión”, pero aquí se considera que el establecimiento de una conexión WebRTC requiere al menos 8 RTT
-
Ejemplo con servidor de señalización
- Con un servidor de señalización como WHIP, se necesitan los siguientes viajes de ida y vuelta
- 1 RTT para TCP
- 1 RTT para TLS 1.3
- 1 RTT para HTTP
- Con un servidor de señalización como WHIP, se necesitan los siguientes viajes de ida y vuelta
-
Servidor de medios
- 1 RTT para ICE
- 2 RTT para DTLS 1.2
- 2 RTT para SCTP
- Algunos protocolos pueden evitar 0.5 RTT mediante pipelining, así que el cálculo exacto es complejo, pero en conjunto se requieren muchos viajes de ida y vuelta
- Este procedimiento existe porque WebRTC debe soportar P2P, y aunque el servidor tenga una IP fija debe seguir el mismo proceso
- Cuando el servidor de señalización y el servidor de medios corren en el mismo host o proceso, se terminan haciendo dos handshakes redundantes y costosos
Una estructura que empuja a hacer un fork de WebRTC
- Se considera que, por sus muchas limitaciones, WebRTC prácticamente empuja a hacer un fork del protocolo
- WebRTC está compuesto por unas 45 RFC y borradores de estándares de facto como TWCC y REMB, lo que hace pesada su implementación
- Se afirma que la implementación del navegador está controlada por Google y adaptada a Google Meet, lo que representa una amenaza existencial para las apps de videoconferencia
- También se sostiene que la razón por la que las apps de videoconferencia, excepto Google Meet, incentivan instalar apps nativas es para evitar usar WebRTC
- Discord hizo un fork profundo de WebRTC en su cliente nativo y no implementa gran parte de SDP, ICE, STUN, TURN, DTLS, SCTP ni SRTP, pero para el cliente web sigue teniendo que implementar el conjunto completo
- Aunque OpenAI seguramente tiene suficientes recursos, se considera mejor reemplazar WebRTC por otro enfoque con soporte en navegador en vez de hacerle un fork
Alternativas: WebSockets y QUIC
- Como alternativa inicial a WebRTC para Voice AI, se propone WebSockets
- Se puede aprovechar la infraestructura existente de TCP/HTTP
- No hace falta construir un balanceador de carga WebRTC personalizado
- Se considera que encaja bien con Kubernetes y que escala
- En este contexto, el head-of-line blocking podría no ser una desventaja sino una experiencia de usuario deseable
- La idea es que es preferible entregar el audio en orden a que falten partes del prompt de voz
- Si en algún momento hace falta descartar ciertos paquetes o priorizarlos, se plantea que OpenAI debería usar WebTransport, como en MoQ
- La configuración de conexión de QUIC puede hacerse con QUIC+TLS en 1 RTT, algo más simple que los múltiples handshakes de WebRTC
Ventajas del Connection ID de QUIC
- QUIC abandona el enrutamiento basado en IP/puerto de origen y pone un
CONNECTION_IDen todos los paquetesCONNECTION_IDpuede tener entre 0 y 20 bytes- Lo importante es que este valor lo elige el receptor
- El servidor QUIC puede generar un
CONNECTION_IDúnico para cada conexión- Puede usar un solo puerto y aun así identificar conexiones cuyo IP/puerto de origen haya cambiado
- Si cambia la dirección de origen, QUIC cambia automáticamente a la nueva dirección sin cortar la conexión, a diferencia de TCP
- Se considera que la idea de RFC9146 fue tomada de QUIC
Balanceo de carga sin estado
- El balanceador de carga de OpenAI depende de estado compartido, como muchos otros balanceadores
- Tiene que almacenar un mapeo desde IP/puerto de origen hacia el servidor backend
- Como el balanceador puede reiniciarse o caerse, hace falta almacenar ese mapeo
- OpenAI usa una instancia de Redis para guardar la relación entre IP/puerto de origen y servidor backend
- Se evalúa como un método simple y fácil
- QUIC-LB ofrece un enfoque más simple sin base de datos
- Cuando el cliente inicia una conexión QUIC, el balanceador reenvía el paquete a un servidor backend válido
- El servidor backend completa el handshake codificando su propio ID en el
CONNECTION_ID - Después, todos los paquetes QUIC contienen el ID del servidor backend
- El balanceador solo necesita decodificar los primeros bytes y reenviar al servidor correspondiente, sin claves de cifrado ni tablas de enrutamiento
- Este esquema puede mantenerse incluso si el servidor se reinicia
- Que sea sin estado también significa que no hay estado global
- El balanceador puede recibir en una dirección anycast global y reenviar globalmente al servidor backend indicado
- Se menciona que Cloudflare usa esto de forma extensa
- AWS NLB ofrece balanceo de carga QUIC usando QUIC-LB
Combinación de anycast y unicast
- En el caso de OpenAI, parece que la estructura asigna las conexiones a balanceadores regionales; funcionalmente sirve, pero se propone Anycast como una mejor aproximación
preferred_addressde QUIC se evalúa como una función importante para el balanceo de carga-
Cómo funciona
- Varios servidores backend alrededor del mundo anuncian la misma dirección anycast
1.2.3.4 - Cuando el cliente intenta conectarse a
1.2.3.4, los routers de internet entregan el paquete a uno de los servidores - Cada servidor QUIC también puede tener su propia dirección unicast
5.6.7.8 - Anycast se usa para el handshake, y la conexión con estado se mantiene por unicast
- Varios servidores backend alrededor del mundo anuncian la misma dirección anycast
-
Flujo de ejemplo
- El servidor recibe paquetes QUIC en
1.2.3.4y5.6.7.8 - El cliente envía el paquete de handshake QUIC a
1.2.3.4 - El servidor crea la conexión QUIC e informa
preferred_address=5.6.7.8 - A partir de ahí, el cliente envía los siguientes paquetes a
5.6.7.8 - Si el servidor está sobrecargado y no quiere aceptar nuevas conexiones, basta con dejar de anunciar
1.2.3.4 - Las conexiones existentes no se cortan porque siguen en unicast
- La dirección anycast actúa prácticamente como un health check
- En esta estructura se considera que no hace falta un balanceador separado
- El servidor recibe paquetes QUIC en
Límites y conclusión
- Se reconoce que los ingenieros de OpenAI son muy capaces y están bajo presión para escalar masivamente de inmediato
- Aun así, se considera que en Voice AI WebRTC, aunque parezca la opción obvia, no encaja bien con el producto y además es difícil de escalar
- MoQ tampoco encaja perfectamente con Voice AI
- En audio 1:1, gran parte de la semántica de caché y fan-out no resulta útil
- Aun así, la conclusión es que hay que usar QUIC
1 comentarios
Comentarios en Hacker News
No leí todo el texto hasta el final, pero creo que el autor sí entiende, en lo fundamental, el propósito de WebRTC. Que diga ser experto y que haya construido SFU en Go/Rust en varias empresas puede ser cierto, pero el historial técnico no garantiza por sí solo la validez de la conclusión.
Puede que lo haya entendido mal, pero parece tratar STUN y DTLS como si fueran factores acumulativos relacionados entre sí en el problema del tiempo de ida y vuelta, cuando en realidad son elementos bastante ortogonales. También siento que pierde el hilo al dedicar demasiado tiempo a decir que no hay retransmisión de paquetes y repetir que en Discord se esforzaron muchísimo.
La parte de RTC en WebRTC significa comunicación en tiempo real, y a la gente a veces le molestan más el audio atrasado o con velocidad irregular que algún sonido con paquetes perdidos. Aquí estamos hablando de voz humana.
Si no quieres tolerar pérdida de paquetes, entonces usa un protocolo basado en TCP en lugar de UDP. Pero si envías voz por TCP en una red mala, del lado receptor habrá pausas mientras espera el siguiente paquete correcto. Si tras varios segundos vuelven a llegar paquetes, entonces hay que decidir si reproducir el audio acumulado a velocidad normal o acelerarlo para alcanzar a otros canales, y por lo general a la gente no le gusta esa experiencia.
Si dejamos un momento de lado WebRTC y pensamos en TCP y UDP para voz, hay una razón por la que VoIP ha sido basado en UDP desde los años 90.
Primero, sobre la parte técnica, sí creo que existe un futuro que no sea WebRTC. Pero no sé si esa dirección coincide con lo que buscan WebTransport+WebCodecs y similares.
Decir que el usuario está dispuesto a esperar 200 ms más para que un prompt lento/caro sea más preciso va totalmente en contra del feedback que yo recibo. Los usuarios quieren una respuesta inmediata. Si hay latencia al generar la respuesta o al manejar interrupciones, desaparece la sensación de magia. Tampoco quieren que se envíe más rápido que en tiempo real. Si el usuario interrumpe al modelo a mitad, haber enviado un audio de 3 minutos del que solo se reprodujeron 10 segundos fue desperdiciar ancho de banda.
Sobre la afirmación de que TTS es más rápido que tiempo real, la IA de voz más moderna o hacia la que se apunta se está alejando del esquema que describe el autor: https://research.nvidia.com/labs/adlr/personaplex/ apunta a entrada/salida incremental en bloques de 20 ms.
La parte de querer que la IP/puerto original del usuario no cambie sí está soportada. Si llega una nueva IP en el ufrag, puede manejarse.
También es incorrecto decir que se requieren al menos 8 viajes de ida y vuelta: https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/
Elegir transmitir audio por WebSocket hace que pierdas funciones como AEC y empuja la complejidad al cliente. Gracias a la simplicidad de WebRTC, es decir, el flujo createOffer -> setRemoteDescription, la gente puede empezar fácil. Con Realtime API + WebSocket, muchos desarrolladores sufrieron porque había mucho código y demasiadas cosas que manejar por su cuenta.
Si yo tuviera que escoger, mantendría el modelo Offer/Answer, pero usaría QUIC en lugar de DTLS+SCTP. Tal vez incluso se podría usar RTP sobre QUIC. No tengo una preferencia fuerte por el protocolo en sí, pero no tengo claro cómo desplegar código con una huella mucho mayor a múltiples clientes y a clientes de clientes.
No soy experto en TTS, pero no veo cuál es la ventaja de ir soltando el resultado poco a poco. Al silicio no le importa qué tan rápido aumentan los números del tiempo.
Hay casos donde el cliente sabe que cambió su IP y puede renegociar ICE, pero muchas veces no lo sabe y normalmente se espera que el servidor detecte el cambio. Pero con la configuración actual del balanceador de carga eso es imposible. No es un gran problema, pero en una situación donde ya hay muchos pasos que superar, sí se siente como una pena.
Si ese borrador significa 7 RTT en vez de 8 RTT, algunas partes pueden pipelinearse, así que la cifra real podría ser menor. Pero el problema real es que, solo porque puede usarse P2P, terminas con un servidor de señalización obligatorio y un doble handshake TLS.
WebRTC es fácil para desarrolladores nuevos porque es una app de videoconferencia de caja negra. Pero en una empresa grande como OpenAI, esa caja negra empieza a crear problemas que podrían resolverse con primitivas de nivel más bajo.
De verdad valdría la pena probar RTP over QUIC, y hasta estaría dispuesto a ayudar. Si preocupa el tamaño del código, el navegador —y algún día el sistema operativo— ofrecerá una librería QUIC. Si te mueves hacia algo más cercano a MoQ, QUIC maneja fragmentación, retransmisión, control de congestión, etc., así que la aplicación se vuelve sorprendentemente pequeña.
La gran limitación de RoQ/MoQ es que, como QUIC aplica control de congestión incluso a los datagramas, no puedes implementar GCC. Al enviar desde el navegador, por un tiempo quedarás atado a cubic/BBR.
Mi trabajo actual es voz/video conferencias y llamadas 1:1, y la complejidad de WebRTC es enorme. Sí nos permitió arrancar rápido el producto, pero cuando haces cosas raras es difícil arreglarlo, incluso habiéndolo forkeado para cliente.
Podría escribir una larga queja sobre TURN. De hecho, todo el paquete de protocolos de WebRTC parece diseñado para un internet que no existe.
En TURN, cuando el cliente solicita una asignación, debería recibir un rendezvous id en vez de un puerto temporal. Entonces el peer podría conectarse al servidor TURN por el puerto del servicio y pedir una conexión para ese rendezvous id, sin que el cliente tenga que conocer la dirección del peer ni agregar permisos. Se reduciría la comunicación necesaria hasta establecer una conexión por relay de extremo a extremo. Un clúster avanzado podría codificar información en el id para que el cliente y el peer se conecten cada uno al servidor TURN más cercano y luego los servidores se enlacen entre sí. Un clúster menos sofisticado tendría que compartir junto al id la IP del servidor TURN y el puerto del servicio.
Me pegó fuerte esa parte de preguntar por qué haría falta saber el timestamp real de visualización y cómo corresponde al tiempo real. Parece que nadie entre quienes hicieron WebRTC ha intentado sincronizar flujos de datos de distintas fuentes con precisión de milisegundos.
Hice una demo de estabilización de video en el navegador usando webcam y un módulo IMU, y la latencia de la ruta video->rtc->browser y la de sensor->websocket->browser era muy distinta y además variable. La solución obvia era enviar timestamps UTC en los datos del sensor y sincronizar en el navegador, pero era imposible porque el video no tenía una referencia de timestamp UTC.
Si controlas ambos lados del pipe de WebRTC, puedes hacer cosas curiosas como enviar el timestamp UTC del inicio del stream, pero eso no resuelve el jitter del navegador. Como prueba de concepto funcionó suficientemente bien, pero la solución completa hubo que rediseñarla.
Tengo bastante experiencia en esta área e incluso algunas patentes en trámite. En Alexa, el dispositivo establecía una conexión con el servidor y la dejaba abierta; al detectar la wake word, enviaba sobre esa conexión algo esencialmente parecido a HTTP2/SPDY. Así se podía empezar el procesamiento de STT antes de que el usuario terminara de hablar, y solo quedaba la latencia de procesar los últimos fragmentos.
La respuesta volvía por la misma conexión.
En el caso de OpenAI, es más difícil mantener una conexión persistente siempre abierta como Alexa, pero si en el teléfono usas HTTP2, iOS y Android casi se encargan solos de esa conexión.
El autor tiene razón. No hace falta un protocolo en tiempo real, y es más importante recibir todos los datos. Los usuarios casi no notan la latencia mientras no supere los 500 ms. Sobre todo en la era móvil, la mayoría ya está acostumbrada a que incluso la comunicación humana en tiempo real tenga retraso.
Si trabajas en OpenAI o Anthropic, puedes escribirme. Puedo contar más detalles.
La latencia de transporte simplemente se suma encima de todas las demás latencias ya grandes.
Por eso supongo que eligieron la solución de menor latencia posible para reducir la latencia end-to-end de todo el pipeline.
La analogía con la latencia de voz entre humanos no encaja. En ese caso se está tratando al ser humano como si no tuviera latencia.
500 ms está cerca del piso de lo que hoy se logra en implementaciones de voz de punta si tienes suerte, no escatimas dinero y hasta usas técnicas caras como speculative decoding y reasoning. Solo la etapa del LLM tarda 450 ms. En IA de voz comercial, cada ms importa, y agregar solo 200~300 ms empeora mucho la calidad de la conversación.
Nuestro negocio maneja sobre todo mucha voz para usuarios no técnicos. El año pasado, cuando la latencia entre turnos era de 1200~1500 ms, había mucha confusión de usuarios, interrupciones, abandono de la conversación y una experiencia desagradable en general. Ahora estamos alrededor de 700 ms según las herramientas necesarias, y ya se acerca a una experiencia razonable comparable con interactuar con una persona real. Estamos gastando bastante dinero para bajar otros 100 ms más.
También hacemos cosas caras y derrochadoras como speculative LLM pass y speculative tool execution. Corremos varias inferencias del LLM mientras el usuario habla y reducimos 100~200 ms, pero sin ejecutar de verdad llamadas a herramientas no idempotentes hasta saber que ese pass sirve y que el usuario no dijo algo importante al final de la frase. Decir que 500 ms da igual me suena a un caso distinto, no a interacción de voz humano-IA.
El problema realmente difícil en IA de voz no son los paquetes de WebRTC que ocasionalmente se pierden, sino el ruido fuerte de fondo, el eco y los acentos. La implementación pulida de AEC de WebRTC al menos ayuda bastante con el eco. Sé que, a escala OpenAI, es un protocolo muy molesto de implementar, pero para aplicaciones que no son hiperescaladas hay buenas soluciones con proveedores comerciales como Daily. El verdadero problema a resolver está en otro lado. Aun así, si le agrego 500 ms a mi presupuesto de latencia, la aplicación muere.
Por desgracia, hay pocos protocolos que uno quiera implementar menos que WebRTC. Para levantar un solo cliente simple, tienes que adaptarte rápidamente a un handshake complejo que siempre parece rehacerse desde cero: SDP, TURN/STUN, ICE candidates, offer, protocolo P2P.
Cuesta incluso imaginar reescribir completo ese trench coat lleno de capas de protocolo y “mejores prácticas” accidentales.
Ojalá haya mejorado con más material educativo y librerías. También sorprende que herramientas como Codex ahora empujen bastante bien estas partes.
En general, la estabilidad de las API del navegador tiene muchos casos límite no documentados, y no es un problema exclusivo de WebRTC.
Es un texto exasperantemente cargado hacia un solo lado. Sí, WebRTC tiene limitaciones, pero apoyarse en el estándar te da mucha precisión y reduce el costo de ingeniería a largo plazo. El hecho de que WebRTC sea complejo no significa que esté mal, sino que el media en tiempo real sobre internet pública es complejo.
El networking es inherentemente stateful. NAT traversal, jitter buffer, control de congestión, pérdida de paquetes, estado del códec, cifrado y routing de sesión no desaparecen solo por poner el audio sobre TCP o WebSocket. Fingir lo contrario no es claridad arquitectónica, es solo mover la complejidad a un lugar menos visible.
Hace 1 año volvió a reescribir un WebRTC SFU en Rust en Discord, así que ya se ve un patrón repetido.
WebRTC está compuesto por unos 45 RFC heredados desde principios de los 2000, además de estándares de facto que técnicamente siguen siendo borradores, como TWCC y REMB. Cuando tienes que implementarlo todo, no es nada divertido.
Puedes considerarlo un experto certificado en WebRTC, y por eso mismo dice que no quiere volver a usar WebRTC nunca más.
Ya lo intentó bastante por la vía convencional, así que me parece que tiene todo el derecho de sostener una opinión en sentido contrario.
No tengo una postura sobre el tema en sí, pero se sentía claramente humano y eso me gustó.
Si lo escribió una IA, entonces sí estamos en problemas.
Estamos en 2026 y las reuniones remotas siguen siendo un desastre. Hay miles de millones de dólares en juego, Zoom con suerte llega a mediocre, y a veces puede ser tan malo como esa cosa de Microsoft. Nunca he visto reuniones remotas que no se sientan torpes, ásperas y caóticas.
Excelente texto. Ojalá se pudiera premiar una entrada de blog cuando quien la escribe realmente es experto en el tema.
Sobre eso de que “WebRTC está diseñado para degradar y tirar mi prompt en malas condiciones de red”, si quieres tiempo real, eso es parte del trato. Si no quieres tiempo real y te imaginas todo como STT -> Prompt -> TTS, entonces quizá ni siquiera haga falta enviar audio por la red.
Toda aplicación de baja latencia tiene que decidir un compromiso de experiencia de usuario entre calidad y latencia. La congestión crea colas, es decir, latencia, y para evitarlo hay que omitir algo, lo que baja la calidad.
La perilla de ajuste entre latencia y calidad en WebRTC viene fija. Es excelente para minimizar la latencia, pero le falta flexibilidad. Aun así, por el soporte del navegador, sigue siendo de hecho una de las pocas opciones, así que igual pienso usar WebRTC.
Pero ahora existe WebTransport. Con un protocolo de propósito general puedes construir un comportamiento parecido al de WebRTC. La aplicación puede elegir cuánto esperar antes de hacer drop/reset de un stream, y no tiene por qué sufrir que alguien más tome esa decisión por ella.
El punto del texto es que los usuarios normalmente sí quieren streaming, pero no quieren drops. El streaming de entrada/salida de audio obviamente se puede hacer sin WebRTC. La aplicación debería poder decidir en qué momento un paquete de audio se considera perdido para siempre: si a los 50 ms, 500 ms o 5000 ms. La idea es que una IA de voz no debería escoger la opción de 50 ms.
Cuando OpenAI responde, ya tiene la mayor parte del audio antes del momento en que el usuario necesita oírlo. Como genera audio más rápido que en tiempo real, un protocolo en tiempo real no parece la elección adecuada.
Estoy ejecutando Gemini Live API sobre una malla cloud administrada de WebRTC y funciona muy bien; llevamos 2 años operándolo. Podríamos intentar WebSocket y manejar nosotros mismos cosas como claves temporales, pero si hablas con gente que opera agentes de voz a gran escala en este espacio, muchos problemas ya están bastante resueltos gracias a WebRTC, Pipecat y todos los recursos invertidos en cosas ya solucionadas.
Sin duda da la impresión de ser excesivo, y realmente puede serlo, pero una vez establecida la conexión, se siente bastante mágico. El tiempo de arranque y el buffering también están resueltos para conexiones de voz más rápidas: https://github.com/pipecat-ai/pipecat-examples/tree/main/ins... El video es más difícil.