Le problème de WebRTC chez OpenAI
(moq.dev)- WebRTC privilégie une faible latence, comme pour les appels de réunion, et supprime agressivement des paquets audio lorsque le réseau est mauvais, mais dans la Voice AI, la dégradation d’un prompt vocal peut nuire davantage à la qualité de la réponse qu’un temps de réponse plus lent
- Le TTS peut produire de l’audio plus vite que le temps réel, ce qui permet au buffering côté client de masquer de courtes perturbations réseau, mais WebRTC impose un rendu basé sur l’heure d’arrivée et un petit buffer de gigue, ce qui oblige à attendre artificiellement pour envoyer les paquets à temps
- WebRTC rend la configuration et l’exploitation des connexions complexes avec des ports temporaires, ICE, DTLS, SCTP, etc., et dans un multiplexage sur port unique, il est difficile d’acheminer les paquets STUN, SRTP/SRTCP, DTLS et TURN vers chaque connexion
- Même si OpenAI exige une mise en relation rapide, WebRTC peut nécessiter au minimum 8 RTT en combinant signalisation et procédures du serveur média, et en raison de sa structure conçue pour prendre en charge le P2P, la même procédure s’applique même si le serveur a une IP fixe
- Comme alternatives, WebSockets et QUIC/WebTransport sont proposés, QUIC prenant plus simplement en charge un port unique, les changements d’adresse, l’équilibrage de charge sans état, ainsi qu’une combinaison d’anycast et d’unicast via
CONNECTION_ID, QUIC-LB etpreferred_address
Pourquoi WebRTC ne convient pas à la Voice AI
- WebRTC a été conçu pour des échanges rapides aller-retour comme les appels de réunion, et quand le réseau se dégrade, il supprime agressivement des paquets audio pour maintenir une faible latence
- Dans la Voice AI, il est plus important que le prompt soit transmis fidèlement, même si l’utilisateur doit attendre un peu plus longtemps la réponse
- Par exemple, si un prompt vocal comme « aller au lavage auto à pied ou en voiture » est altéré, la qualité de la réponse qui suit peut aussi se dégrader
- L’implémentation audio WebRTC des navigateurs suppose fortement une latence temps réel, et selon l’expérience menée chez Discord, la retransmission des paquets audio WebRTC n’était pas possible
- Mise à jour : certaines personnes impliquées dans WebRTC estimaient qu’il pouvait être possible d’activer les NACK audio, mais chez Discord, ils n’ont pas trouvé la bonne manière de manipuler le SDP, et la limite d’un buffer de gigue WebRTC très réduit demeurait
- Même si les agents de Voice AI atteignent un jour une latence au niveau d’une conversation, la réduction de la latence implique des compromis, et il reste incertain que dégrader volontairement des prompts vocaux soit un bon choix
Le problème de buffering entre TTS et WebRTC
- La synthèse vocale (TTS) peut générer de l’audio plus vite que le temps réel
- Par exemple, si un GPU génère 8 secondes d’audio en 2 secondes, l’idéal serait de diffuser l’audio pendant ces 2 secondes de génération, tandis que le client le lit sur 8 secondes et accumule un buffer local
- De cette façon, même en cas de brève perturbation réseau, il est possible que l’utilisateur ne remarque rien
- WebRTC n’est pas adapté à cette approche
- WebRTC ne bufferise pas et rend l’audio selon le moment d’arrivée, les timestamps n’étant pas considérés comme une référence forte pour la lecture
- Le problème devient encore plus délicat lorsqu’il faut aussi gérer la vidéo
- Un service comme OpenAI doit attendre artificiellement avant chaque envoi de paquet audio afin qu’il arrive exactement au moment où il doit être lu
- En cas de congestion réseau, ce paquet audio est alors perdu et n’est pas retransmis
- Au final, on se retrouve avec une architecture qui introduit une latence artificielle puis supprime agressivement des paquets au nom de la « faible latence », ce qui revient un peu à montrer une vidéo YouTube par partage d’écran sans buffering
- WebRTC utilise pour l’audio un buffer de gigue ajusté dynamiquement entre 20 ms et 200 ms, destiné à atténuer la gigue réseau, mais si l’on peut transmettre plus vite que le temps réel, cela n’est plus jugé nécessaire
Limites des ports et de l’identification des connexions
- Un serveur TCP ouvre généralement un port comme
443et accepte des connexions, qui sont identifiées par une combinaison d’IP source, d’IP destination et de ports- Exemple :
123.45.67.89:54321 -> 192.168.1.2:443
- Exemple :
- Si un téléphone passe du Wi‑Fi au cellulaire ou si un NAT modifie l’IP ou le port source, la connexion TCP est interrompue et une nouvelle connexion doit être établie
- Les handshakes TCP et TLS nécessitent au minimum 2 à 3 RTT, et dans le streaming live, l’utilisateur peut percevoir cette coupure réseau
- Pour résoudre ce problème, WebRTC part du principe qu’un port de destination temporaire est alloué à chaque connexion
- Si la session est identifiée uniquement par l’IP et le port de destination, le même utilisateur peut être reconnu même si son IP ou son port source change
- Mais combinée à l’architecture d’OpenAI, cette approche pose des problèmes à grande échelle
- Le nombre de ports disponibles côté serveur est limité
- Les pare-feu bloquent souvent les ports temporaires
- Cela s’intègre mal aux environnements Kubernetes
Pourquoi les services WebRTC passent au multiplexage sur un port unique
- De nombreux services ne suivent pas la spécification WebRTC à la lettre et multiplexent plusieurs connexions sur un seul port
- Chez Twitch, les serveurs WebRTC fonctionnaient sur
UDP:443- À l’origine,
443est le port de HTTPS/QUIC, mais cela permettait de franchir davantage de pare-feu - Le réseau interne d’Amazon n’autorisait apparemment qu’environ 30 ports
- À l’origine,
- Discord utilisait un port par cœur CPU dans la plage
50000-50032- Cette approche risque d’être bloquée par davantage de réseaux d’entreprise
- Le principal problème du multiplexage sur port unique vient du fait que WebRTC agrège plusieurs standards
- Il existe 5 protocoles qui passent directement sur UDP ; distinguer de quel protocole relève un paquet n’est pas très difficile, mais acheminer chaque paquet vers la bonne connexion est le vrai défi
-
Difficultés de routage selon les protocoles
- STUN
- Il est possible de choisir un
ufragunique et de router à partir de celui-ci
- Il est possible de choisir un
- SRTP/SRTCP
- Le navigateur choisit une valeur
ssrcarbitraire, sur laquelle on peut généralement s’appuyer pour le routage
- Le navigateur choisit une valeur
- DTLS
- La situation suppose de pouvoir compter sur une prise en charge large de RFC9146
- TURN
- L’auteur indique ne pas avoir d’expérience d’implémentation sur ce point
- OpenAI a indiqué ne parser que STUN, puis traiter DTLS, RTP et RTCP de manière opaque à partir d’un état mis en cache
- Cela s’interprète comme une architecture qui suppose que l’IP et le port source de l’utilisateur ne changent pas
- Le navigateur peut aussi générer aléatoirement le même
ssrc - En cas de collision et sans mapping IP/port source, Discord identifie la connexion en essayant de déchiffrer le paquet avec chaque clé de déchiffrement possible jusqu’à trouver la bonne
- STUN
La latence aller-retour dans l’établissement d’une connexion WebRTC
- OpenAI a présenté comme exigence une « mise en relation rapide permettant à l’utilisateur de parler dès le début de la session », mais l’établissement d’une connexion WebRTC nécessiterait au minimum 8 RTT
-
Exemple avec le serveur de signalisation
- En prenant un serveur de signalisation comme WHIP, les allers-retours suivants sont nécessaires
- 1 RTT pour TCP
- 1 RTT pour TLS 1.3
- 1 RTT pour HTTP
- En prenant un serveur de signalisation comme WHIP, les allers-retours suivants sont nécessaires
-
Serveur média
- 1 RTT pour ICE
- 2 RTT pour DTLS 1.2
- 2 RTT pour SCTP
- Certains protocoles peuvent éviter 0,5 RTT grâce au pipelining, donc le calcul exact est complexe, mais dans l’ensemble il faut beaucoup d’allers-retours
- Cette procédure existe parce que WebRTC doit prendre en charge le P2P, et même si le serveur dispose d’une IP fixe, la même séquence reste nécessaire
- Lorsque le serveur de signalisation et le serveur média tournent sur le même hôte ou dans le même processus, des handshakes redondants et coûteux ont lieu deux fois
Une architecture qui pousse à forker WebRTC
- Selon l’auteur, WebRTC pousse de fait à un fork du protocole en raison de ses nombreuses limites
- WebRTC se compose d’environ 45 RFC et de brouillons devenus standards de fait comme TWCC et REMB, ce qui alourdit fortement la charge d’implémentation
- L’implémentation des navigateurs est contrôlée par Google et alignée sur Google Meet, ce qui est présenté comme une menace existentielle pour les applications de visioconférence
- Toujours selon cette analyse, si les applications de visioconférence hors Google Meet poussent à l’installation d’apps natives, c’est aussi pour éviter d’utiliser WebRTC
- Discord a fortement forké WebRTC dans son client natif et n’implémente plus la majeure partie de SDP, ICE, STUN, TURN, DTLS, SCTP, SRTP, etc., mais doit toujours implémenter l’ensemble complet pour le client web
- Même si OpenAI a les moyens nécessaires, l’auteur estime qu’il vaudrait mieux remplacer WebRTC par une autre approche compatible navigateur plutôt que de le forker
Alternatives : WebSockets et QUIC
- Comme alternative de départ à WebRTC pour la Voice AI, WebSockets est proposé
- Cela permet de réutiliser l’infrastructure TCP/HTTP existante
- Il n’est pas nécessaire de créer un load balancer WebRTC sur mesure
- L’approche est jugée compatible avec Kubernetes et facilement scalable
- Le head-of-line blocking n’est pas vu ici comme un défaut, mais comme une expérience utilisateur potentiellement préférable
- L’hypothèse est qu’il vaut mieux transmettre les éléments du prompt vocal dans l’ordre que d’en perdre une partie
- Si un jour il devient nécessaire de supprimer certains paquets ou de leur donner des priorités, l’auteur estime qu’OpenAI devra utiliser WebTransport, à l’image de MoQ
- L’établissement d’une connexion QUIC est possible en 1 RTT pour QUIC+TLS, ce qui est plus simple que les multiples handshakes de WebRTC
Avantages du Connection ID de QUIC
- QUIC abandonne le routage basé sur l’IP et le port source, et inclut un
CONNECTION_IDdans tous les paquetsCONNECTION_IDpeut faire entre 0 et 20 octets- Le point important est que cette valeur est choisie par le destinataire
- Un serveur QUIC peut générer un
CONNECTION_IDunique pour chaque connexion- Il peut ainsi utiliser un port unique tout en identifiant des connexions dont l’IP ou le port source ont changé
- Si l’adresse source change, QUIC bascule automatiquement vers la nouvelle adresse au lieu de casser la connexion comme TCP
- L’idée de RFC9146 est présentée comme dérivée de QUIC
Équilibrage de charge sans état
- Le load balancer d’OpenAI repose sur un état partagé, comme beaucoup d’autres load balancers
- Il faut stocker un mapping entre l’IP/port source et le serveur backend
- Comme le load balancer peut redémarrer ou planter, un stockage pour ce mapping est nécessaire
- OpenAI utilise une instance Redis pour conserver le mapping entre IP/port source et serveur backend
- Cette approche est jugée simple et facile
- QUIC-LB propose une méthode plus simple, sans base de données
- Lorsqu’un client démarre une connexion QUIC, le load balancer transfère les paquets vers un serveur backend approprié
- Le serveur backend termine le handshake et encode son propre identifiant dans le
CONNECTION_ID - Tous les paquets QUIC suivants contiennent alors l’identifiant du serveur backend
- Le load balancer n’a qu’à décoder les premiers octets pour transmettre le paquet au bon serveur, sans clé de chiffrement ni table de routage
- Cette méthode peut continuer à fonctionner même si un serveur redémarre
- L’absence d’état signifie aussi l’absence d’état global
- Le load balancer peut recevoir sur une adresse anycast globale et transférer globalement vers le serveur backend indiqué
- Cloudflare utiliserait largement cette approche
- AWS NLB propose un équilibrage de charge QUIC reposant sur QUIC-LB
Combiner anycast et unicast
- Dans le cas d’OpenAI, l’architecture semble attribuer les connexions à un load balancer régional ; cela fonctionne sur le plan fonctionnel, mais l’anycast est présenté comme une meilleure approche
preferred_addressde QUIC est considéré comme une fonctionnalité importante pour le load balancing-
Fonctionnement
- Plusieurs serveurs backend à travers le monde annoncent la même adresse anycast
1.2.3.4 - Lorsqu’un client tente une connexion vers
1.2.3.4, les routeurs Internet dirigent les paquets vers l’un des serveurs - Chaque serveur QUIC peut aussi disposer de sa propre adresse unicast
5.6.7.8 - L’anycast sert pour le handshake, puis les connexions avec état sont maintenues en unicast
- Plusieurs serveurs backend à travers le monde annoncent la même adresse anycast
-
Exemple de flux
- Le serveur reçoit des paquets QUIC sur
1.2.3.4et5.6.7.8 - Le client envoie les paquets de handshake QUIC à
1.2.3.4 - Le serveur crée la connexion QUIC et annonce
preferred_address=5.6.7.8 - Le client envoie ensuite les paquets suivants à
5.6.7.8 - Si le serveur est surchargé et ne veut plus accepter de nouvelles connexions, il lui suffit d’arrêter d’annoncer
1.2.3.4 - Les connexions existantes ne sont pas coupées, puisqu’elles restent sur l’adresse unicast
- L’adresse anycast agit pratiquement comme un health check
- Dans cette architecture, un load balancer séparé n’est pas jugé nécessaire
- Le serveur reçoit des paquets QUIC sur
Limites et conclusion
- L’auteur reconnaît que les ingénieurs d’OpenAI sont très talentueux et subissent la pression d’un passage immédiat à grande échelle
- Mais pour la Voice AI, WebRTC peut sembler un choix évident alors qu’il présente selon lui une faible adéquation produit et une mise à l’échelle difficile
- MoQ non plus n’est pas parfaitement adapté à la Voice AI
- En audio 1:1, une grande partie de la sémantique de cache et de fan-out n’est pas utile
- Malgré cela, la conclusion reste qu’il faut utiliser QUIC
1 commentaires
Avis sur Hacker News
Je n’ai pas lu l’article jusqu’au bout, mais je pense que l’auteur comprend bien l’objectif de WebRTC dans son principe. Qu’il se présente comme expert et qu’il ait effectivement construit des SFU en Go/Rust dans plusieurs entreprises, c’est une chose, mais l’historique technique ne garantit pas à lui seul la validité de la conclusion
Je me trompe peut-être, mais il semble traiter STUN et DTLS comme des facteurs cumulés liés au problème de temps d’aller-retour, alors qu’en réalité ce sont des éléments assez orthogonaux. Et j’ai aussi eu l’impression qu’il perdait le fil de son argumentation en passant trop de temps sur le fait qu’il n’y a pas de retransmission de paquets, puis en répétant qu’ils avaient énormément travaillé dessus chez Discord
Le « RTC » de WebRTC signifie communication en temps réel, et les gens détestent parfois davantage un audio en retard ou au débit irrégulier qu’un son avec quelques paquets perdus. On parle ici de voix humaine
Si l’on ne veut vraiment pas accepter de perte de paquets, il suffit d’utiliser un protocole basé sur TCP au lieu d’UDP. Mais si on envoie de la voix sur TCP dans de mauvaises conditions réseau, le côté réception se bloque en attendant le prochain paquet correct. Quand les paquets finissent par arriver plusieurs secondes plus tard, il faut alors décider s’il faut lire l’audio accumulé à vitesse normale, ou l’accélérer pour rattraper les autres flux — et en général, les gens n’aiment pas ce genre d’expérience
En oubliant WebRTC un instant pour simplement réfléchir à TCP contre UDP pour la voix, il y a une raison pour laquelle la VoIP est basée sur UDP depuis les années 1990
Pour répondre d’abord sur la partie technique, je pense qu’il existe un futur qui ne repose pas sur WebRTC. En revanche, je ne sais pas si ce futur correspond à la direction prise par WebTransport + WebCodecs et consorts
L’idée que les utilisateurs accepteraient d’attendre 200 ms de plus pour que des prompts lents/chers soient plus précis va exactement à l’encontre des retours que je reçois. Les utilisateurs veulent une réponse immédiate. S’il y a de la latence dans la génération de réponse ou dans la gestion des interruptions, la sensation de magie disparaît. Ils ne veulent pas non plus qu’on envoie plus vite que le temps réel. Si l’utilisateur interrompt le modèle au milieu, envoyer un audio de 3 minutes dont seulement 10 secondes seront jouées, c’est juste gaspiller de la bande passante
Quant à l’affirmation selon laquelle la TTS est plus rapide que le temps réel, les systèmes de voix IA les plus récents / vers lesquels on tend s’éloignent du modèle décrit par l’auteur : https://research.nvidia.com/labs/adlr/personaplex/ et traitent les entrées/sorties petit à petit, par blocs de 20 ms
La partie sur le souhait que l’IP/port source de l’utilisateur ne change pas est prise en charge. Si une nouvelle IP arrive avec le ufrag, c’est gérable
Dire qu’il faut au minimum 8 allers-retours est également faux : https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/
Choisir de streamer l’audio via WebSocket, c’est perdre des fonctions comme l’AEC et repousser la complexité vers le client. La simplicité de WebRTC, à savoir le flux createOffer -> setRemoteDescription, permet aux gens de démarrer facilement. Avec la Realtime API + WebSocket, beaucoup de développeurs ont souffert à cause de la quantité de code et des traitements à gérer eux-mêmes
Si je devais choisir personnellement, je garderais le modèle Offer/Answer mais je remplacerais DTLS+SCTP par QUIC. On pourrait même faire du RTP sur QUIC. Je n’ai pas de préférence très forte pour le protocole lui-même, mais je ne vois pas bien comment distribuer un code bien plus volumineux à plusieurs clients et à des clients de clients
Je ne suis pas spécialiste de la TTS, mais je ne vois pas l’intérêt de faire sortir le résultat petit à petit. Le silicium n’a rien à faire de la vitesse à laquelle les chiffres du temps augmentent
Il y a des cas où le client peut savoir que sa propre IP a changé et relancer une renégociation ICE, mais souvent il ne le sait pas et on s’attend plutôt à ce que le serveur détecte le changement. Or, avec la configuration actuelle du load balancer, c’est impossible. Ce n’est pas un gros problème, mais c’est regrettable quand il y a déjà beaucoup d’étapes à franchir
Si ce draft veut dire 7 RTT et non 8 RTT, certains éléments peuvent être pipelinés, donc la valeur réelle peut être plus basse. Mais le vrai problème, c’est qu’au simple motif qu’un mode P2P pourrait exister, on se retrouve avec un serveur de signalisation obligatoire et une double poignée de main TLS
WebRTC est facile pour les nouveaux développeurs parce que c’est une application de visioconférence en boîte noire. Mais dans une grande entreprise comme OpenAI, cette boîte noire commence à créer des problèmes qui pourraient être corrigés avec des primitives de plus bas niveau
J’aimerais vraiment expérimenter RTP over QUIC et je serais prêt à aider. Si la taille du code vous inquiète, les navigateurs — et un jour les OS — fourniront des bibliothèques QUIC. Si l’on se rapproche de MoQ, QUIC gère la fragmentation, la retransmission, le contrôle de congestion, etc., et l’application devient étonnamment petite
La grande limite de RoQ/MoQ, c’est que QUIC applique aussi le contrôle de congestion aux datagrammes, donc on ne peut pas implémenter GCC. Depuis le navigateur, on sera donc liés pendant un bon moment à cubic/BBR
Mon travail actuel tourne autour de la visioconférence / des appels vocaux 1:1, et la complexité de WebRTC est énorme. Il nous a permis de lancer le produit rapidement, mais dès qu’on veut faire quelque chose d’un peu atypique, c’est difficile à corriger — même en faisant un fork côté client
Je pourrais écrire une longue plainte sur TURN. En fait, tout l’ensemble de protocoles WebRTC donne l’impression d’avoir été conçu pour un Internet qui n’existe pas
Avec TURN, au lieu d’allouer un port temporaire quand le client demande une allocation, il faudrait attribuer un rendezvous id. Le pair pourrait alors se connecter au serveur TURN sur un port de service et demander une connexion pour ce rendezvous id, sans que le client ait besoin de connaître l’adresse du pair ni d’ajouter une permission. Cela réduirait le volume de communication nécessaire jusqu’à la connexion relayée de bout en bout. Un cluster avancé pourrait encoder des informations dans l’id pour que le client et le pair se connectent chacun au serveur TURN le plus proche, puis que les serveurs se relient entre eux. Un cluster moins avancé devrait partager, avec l’id, l’IP du serveur TURN et le port de service
Le passage sur le fait qu’on puisse se demander pourquoi il faudrait connaître l’horodatage réellement affiché et sa correspondance avec le temps réel m’a parlé de façon assez douloureuse. On dirait qu’aucun des créateurs de WebRTC n’a jamais synchronisé des flux de données de sources différentes avec une précision à la milliseconde
J’ai fait une démo de stabilisation vidéo dans le navigateur avec une webcam et un module IMU, et les latences du chemin video->rtc->browser et du chemin sensor->websocket->browser étaient très différentes et très variables. La solution évidente aurait été d’envoyer un horodatage UTC avec les données du capteur et de synchroniser dans le navigateur, mais comme il n’y avait pas de référence UTC pour la vidéo, c’était impossible
Si l’on contrôle les deux extrémités du pipeline WebRTC, on peut faire des choses astucieuses comme envoyer l’horodatage UTC du début du flux, mais cela ne résout pas le jitter du navigateur. C’était suffisant pour une preuve de concept, mais il a fallu repenser toute la solution
J’ai beaucoup d’expérience dans ce domaine et même quelques dépôts de brevet. Chez Alexa, l’appareil établissait une connexion vers le serveur et la gardait ouverte, puis lorsqu’il détectait le wake word, il envoyait dessus quelque chose de très proche de HTTP2/SPDY. Cela permettait de lancer le traitement STT avant même que l’utilisateur ait fini de parler, et il ne restait plus que la latence de traitement des tout derniers fragments
La réponse revenait par la même connexion
Dans le cas d’OpenAI, garder en permanence une connexion persistante ouverte comme Alexa est plus difficile, mais sur téléphone, si l’on utilise HTTP2, iOS et Android gèrent quasiment cette connexion tout seuls
L’auteur a raison. Un protocole temps réel n’est pas indispensable, et il est plus important de recevoir toutes les données. Les utilisateurs remarquent à peine une latence tant qu’elle ne dépasse pas 500 ms. Surtout à l’ère du mobile, la plupart des gens sont déjà habitués à ce qu’il y ait de la latence même dans une communication temps réel entre humains
Si vous travaillez chez OpenAI ou Anthropic, vous pouvez me contacter. Je peux en parler plus en détail
La latence de transport s’ajoute simplement à beaucoup d’autres latences déjà importantes
C’est pourquoi je pense qu’ils ont choisi la solution la plus faible possible en latence pour réduire la latence de bout en bout de tout le pipeline
L’analogie avec la latence de la voix entre humains ne tient pas. Dans ce cas, on traite l’humain comme une entité sans latence
500 ms, c’est plutôt proche du plancher dans les implémentations vocales de pointe actuelles, quand on a de la chance, qu’on ne regarde pas à la dépense, et qu’on utilise même des techniques coûteuses comme le speculative decoding ou le reasoning. L’étape LLM à elle seule prend 450 ms. Dans l’IA vocale en production, chaque milliseconde compte, et même 200 à 300 ms supplémentaires dégradent fortement la qualité de la conversation
Notre activité concerne surtout la voix pour des utilisateurs non techniques. L’an dernier, quand la latence entre tours était de 1200 à 1500 ms, on voyait beaucoup de confusion, d’interruptions, d’abandon de conversation, et une expérience globalement désagréable. Aujourd’hui, on est autour de 700 ms selon les outils nécessaires, et on se rapproche d’une expérience correcte, comparable à une interaction avec une vraie personne. Et on dépense beaucoup pour gratter encore 100 ms
On fait aussi des choses coûteuses et peu efficaces comme des speculative LLM pass ou de l’exécution spéculative d’outils. On gagne 100 à 200 ms en lançant plusieurs inférences LLM pendant que l’utilisateur parle, tout en n’exécutant pas réellement les appels d’outils non idempotents tant qu’on ne sait pas que ce passage sera exploitable et que l’utilisateur n’a pas gardé l’information clé pour la fin de sa phrase. Dire que 500 ms n’ont pas d’importance me semble relever d’un autre cas d’usage que l’interaction vocale humain-IA
Les vrais problèmes difficiles de l’IA vocale, ce ne sont pas les paquets WebRTC qui tombent parfois, mais le bruit de fond important, l’écho, les accents. L’implémentation AEC bien rodée de WebRTC aide au moins assez bien sur l’écho. Je sais que c’est un protocole extrêmement pénible à implémenter à l’échelle d’OpenAI, mais pour des applications moins massives, il existe pas mal de solutions correctes avec des fournisseurs commerciaux comme Daily. Les vrais problèmes à résoudre sont ailleurs. Cela dit, si on ajoute 500 ms à mon budget de latence, l’application meurt
Malheureusement, il existe peu de protocoles aussi pénibles à implémenter que WebRTC. Rien que pour lancer un simple client, il faut vite s’adapter à SDP, TURN/STUN, ICE candidates, offer, protocole P2P, et à une poignée de main complexe qu’on réimplémente depuis zéro à chaque fois
Il est difficile même d’imaginer réenfiler ce trench-coat composé de couches et de couches de protocoles et de « bonnes pratiques » involontaires
J’espère que la multiplication des ressources pédagogiques et des bibliothèques améliore les choses. C’est aussi surprenant de voir à quel point des outils comme Codex arrivent maintenant à bien pousser ce genre de sujets
Plus généralement, il existe beaucoup de cas limites non documentés dans la stabilité des API de navigateur, et ce n’est pas propre à WebRTC
C’est un billet exaspérément à charge. Oui, WebRTC a des limites, mais s’appuyer sur un standard permet d’obtenir beaucoup de justesse et de réduire les coûts d’ingénierie à long terme. Le fait que WebRTC soit complexe ne veut pas dire que c’est mauvais, cela veut dire que les médias temps réel sur l’Internet public sont complexes
Le réseau est par nature stateful. La traversée de NAT, le jitter buffer, le contrôle de congestion, la perte de paquets, l’état des codecs, le chiffrement, le routage de session — rien de tout cela ne disparaît si l’on met l’audio sur TCP ou WebSocket. Faire comme si c’était le cas, ce n’est pas de la clarté architecturale, c’est simplement déplacer la complexité là où elle se voit moins
Il y a un an, chez Discord, il a réécrit un SFU WebRTC en Rust, et on peut commencer à voir un schéma récurrent
WebRTC, c’est environ 45 RFC qui s’enchaînent depuis le début des années 2000, plus des standards de fait comme TWCC ou REMB qui sont techniquement encore des drafts. Quand il faut tout implémenter, ce n’est vraiment pas amusant
On peut tout à fait le considérer comme un expert WebRTC reconnu, et c’est précisément pour cela qu’il dit ne plus jamais vouloir utiliser WebRTC
Il a largement assez essayé la voie habituelle ; on peut donc penser qu’il a pleinement gagné le droit d’avoir une opinion opposée
Je n’ai pas d’avis tranché sur le fond du sujet, mais le texte avait clairement une texture humaine qui m’a plu
Si jamais c’était écrit par une IA, alors ce serait vraiment grave
Nous sommes en 2026 et les réunions à distance restent toujours aussi médiocres. Des milliards de dollars sont en jeu, même Zoom est au mieux banal, et parfois c’est aussi mauvais que le truc de Microsoft. Je n’ai jamais vu la visioconférence être autre chose qu’un bazar maladroit et rugueux
Excellent billet. J’aimerais qu’on puisse attribuer un prix aux articles de blog quand l’auteur est un expert du domaine
Concernant la phrase « WebRTC est conçu pour dégrader et laisser tomber mon prompt dans de mauvaises conditions réseau », si l’on veut du temps réel, c’est le prix à payer. Si l’on ne veut pas du temps réel et qu’on imagine tout comme STT -> Prompt -> TTS, il se peut même qu’il ne soit pas nécessaire d’envoyer l’audio sur le réseau au départ
Toute application à faible latence doit arbitrer l’expérience utilisateur entre qualité et latence. La congestion crée des files d’attente, donc de la latence, et pour l’éviter, il faut sauter quelque chose, ce qui réduit la qualité
Le curseur latence / qualité de WebRTC est figé. C’est excellent pour minimiser la latence, mais cela manque de flexibilité. Malgré tout, à cause du support navigateur, cela reste pratiquement l’un des seuls choix possibles, donc je compte encore utiliser WebRTC
Mais il y a désormais WebTransport. On peut construire avec lui un comportement proche de WebRTC sur un protocole générique. L’application peut choisir combien de temps attendre avant d’abandonner / réinitialiser un flux, au lieu de subir cette décision
Le fond du propos, c’est que les utilisateurs veulent généralement du streaming, mais pas des pertes. Il va de soi qu’on peut streamer l’entrée et la sortie audio sans WebRTC. C’est l’application qui devrait pouvoir décider à quel moment un paquet audio est perdu pour toujours : 50 ms, 500 ms ou 5000 ms. L’argument, c’est que l’IA vocale ne devrait pas choisir l’option 50 ms
Quand OpenAI répond, il a déjà la majeure partie de l’audio avant le moment où l’utilisateur doit l’entendre. Comme il génère l’audio plus vite que le temps réel, un protocole temps réel n’est pas le bon choix
Je fais tourner l’API Gemini Live sur un mesh cloud WebRTC managé, et cela fonctionne très bien ; c’est en production depuis 2 ans. On peut essayer WebSocket et gérer soi-même des clés temporaires, etc., mais quand on parle avec des gens qui exploitent des agents vocaux à grande échelle dans cet espace, WebRTC, Pipecat, et l’énorme quantité de ressources investies dans des problèmes déjà résolus couvrent une bonne partie du besoin
Cela donne clairement une impression de surdimensionnement, et c’est parfois le cas, mais une fois la connexion établie, c’est assez magique. Le temps de démarrage et le buffering ont aussi été résolus pour permettre des connexions vocales plus rapides : https://github.com/pipecat-ai/pipecat-examples/tree/main/ins... La vidéo est plus difficile