Histoire et présentation de WebRTC
WebRTC , avec RTC pour Real Time Communication, est une norme regroupant un ensemble de technologies permettant d'émettre et de recevoir avec des faibles latences des flots de sons, d'images et de données.
Le WebRTC a permis l'emergence de solutions de visioconférence sans installer d'application, avec juste un navigateur web, sans installation de plugin préalable.
Techniquement, WebRTC est une rupture avec la pile logicielle web existante. HTML5 avait amené du multimédia avec les balises <video>
et <audio>
, pour clore l'ère douloureuse des plugins et de Flash.
Le lobbying de Mozilla a permis de normaliser l'accès universel aux codecs vidéos. Dans un premier temps, un compromis avec Cisco a permis l'usage de H264, pour enfin avoir une solution vraiment libre avec VP8 (via un rachat de Google), puis VP9 , en attendant le très prometteur AV1 .
Le vrai changement pour le web est l'arrivée de l'UDP dans sa stack, protocole habituellement cantoné au DNS. Le Web misait tout sur TCP, comme socle d'un protocole HTTP omniprésent.
Même si WebRTC est un chamboulement pour le Web, il n'a rien inventé et se contente de piocher dans la stack téléphonie/vidéo IP, normalisée par l' IETF . Les codecs ne sont plus spécifiques (adieu G.771 ), mais la communication se fait en RTP , négociée en ICE avec l'aide de STUN/TURN.
Deuxième chamboulement, la communication point à point. Avant, un navigateur web se planquait derrière son NAT, se comportant comme un client se connectant à un serveur .
Ça, c'était avant ! Maintenant, deux navigateurs peuvent échanger des flots de données, sans passer par l'intermédiaire d'un serveur et donc, sans passer par un potentiel censeur.
WebRTC permet a un client web de faire des échanges pair-à-pair, mais il aura du mal à se passer d'un nœud central pour établir chaque connexion.
WebRTC est implémenté par les navigateurs Web, mais il n'est en rien lié à HTML5. Il existe des implémentations en golang (pion), python (aiortc) ou gstreamer avec des bindings C, python et JS.
Principes de fonctionnements
WebRTC est conçu pour établir des connexions point à point, en UDP, pour gérer au mieux les fluctuations du réseau.
Établir une session
La norme WebRTC ne spécifie pas comment est négocié l'établissement de la communication, mais n'importe quel système pour discuter sur internet fera l'affaire. Un site web permettant de discuter via une websocket est la solution classique, mais on peut simplement utiliser de l'HTTP en REST, ou chercher plus exotique, comme utiliser du XMPP, les flots d'HTTP/2, ou ce que vous voulez, WebRTC ne vous jugera pas.
Sur ce canal, chaque participant fait une offre en SDP (pour Session Description Protocol) pour déclarer les paramètres multimédia (codecs, débit, etc.).
Établir une connexion avec ICE
La négociation ICE va déterminer comment deux interlocuteurs vont pouvoir établir une connexion.
STUN
Pour connaitre les IPs publics des interlocuteurs, et ouvrir les ports des passerelles, il est possible de passer par un service STUN. Il existe plein de serveurs STUN sans authentification, utilisable librement.
TURN
Si les routeurs des interlocuteurs ne sont pas conciliants, il sera possible d'utiliser un service TURN, qui servira de proxy, ce qui va consommer de la bande passante. Il faudra déployer votre service TURN, avec une authentification, pour ne pas offrir votre bande passante à n'importe qui.
Il est déconseillé de faire l'impasse sur un serveur TURN quand on fait du WebRTC, les clients détermineront s’ils ont besoin de l'utiliser ou non.
Alice est caché derrière sa passerelle, Bob passe par le serveur TURN pour lui envoyer des messages. Coup de bol, Bob est accessible en direct, mais il est aussi possible que les deux participants passent par TURN.
Pair-à-pair
Il est possible en WebRTC d'établir une connexion unidirectionnelle : on peut regarder la télé sans allumer sa webcam ou écouter la radio sans causer.
Il est aussi possible d'établir des connexions pair-à-pair entre plus de deux interlocuteurs. La discussion en pair-à-pair implique que chacun envoie son flot multimédia à tous les autres participants, et traditionnellement, une connexion Internet est asymétrique, avec un flot montant faiblard.
Les groupes pair-à-pair ne fonctionneront qu'avec de tout petits groupes.
Alice envoie un flot montant à Bob et un autre à Charly, qui font la même chose, chacun gère n-1 flots.
WebRTC n'est pas réservé aux humains, les robots aussi peuvent participer. Pour un groupe de discussion, le plus simple et que chaque humain se connecte au robot, et que le robot envoie les réponses aux humains. Ainsi, chaque humain n'établit qu'une seule connexion montante (couteuse), et le robot, qui est sur un serveur, avec une grosse connexion, pourra assumer une connexion vers chacun des humains.
Pour les services de groupes de discussion, il existe deux patterns : SFU (pour Selective Forwarding Unit) et MCU (pour Multipoint Conferencing Unit).
SFU
En SFU, le serveur se contente de faire le passe-plat avec les paquets et ne lira pas le contenu multimédia, juste les entêtes. C'est peu couteux en CPU, la latence est faible.
Alice, tout comme Bob et Charly, envoie un flot au serveur, ce sera leur unique flot montant. Le serveur recopie le flot d'Alice et le pousse vers Bob et Charly, et fera la même chose avec le flot de Bob et Charly. Le serveur reçoit n flots, et en envoie (n-1)*n.
Un SFU civilisé sera capable de distinguer les images clefs des images intermédiaires, ordonnera les paquets mélangés, et fera des choix sur quoi jeter quand un client a sa connexion saturée.
Le SFU sera beaucoup plus fluide si les clients gèrent le simulcast , et enverront leurs flots dans différentes résolutions, le SFU pourra alors choisir lequel envoyer selon le débit gérable pour chacun des utilisateurs.
MCU
Le MCU va mixer les flux qu'il reçoit, pour en créer un nouveau, qu'il compressera dans différentes résolutions, et choisira la résolution à envoyer aux différents utilisateurs. Le serveur va manger du CPU, du GPU s'il peut. En théorie, un seul flot descendant sera mieux compressé qu'un bouquet de flots, par contre, la latence occasionée par le mixage va être conséquente et pourra gêner une discussion.
Alice envoie un flot montant vers le serveur, le serveur envoie un flot mixé vers Alice.
Retour vers le futur
Vous le remarquerez, la tendance est clairement aux trigrames et il y a une course à la feature entre les différents acteurs, que ce soit les clients lourds (Zoom, Skype, etc.) ou les navigateurs webs pour proposer des nouveautés et se démarquer des concurrents.
SVC
Notre premier trigrame est SVC (Scalable Video Coding), l'évolution de multicast qui permettra d'envoyer un seul flot dans plusieurs résolutions, et le SFU sera capable simplement (sans décompresser) de piocher dans ce flot montant pour choisir une seule résolution à envoyer comme flot descendant. Le schéma SVC est joli, bon courage pour comprendre ce que ça représente. A voir qui sera le premier à l'implémenter.
SVC fonctionne avec les formats vidéos VP9 et AV1.
RED
RED pour REDundant audio data , améliore l'organisation des données dans RTP. Statistiquement, les pertes de paquets sur Internet sont brèves et distantes, ce n'est pas la ligne qui tombe, mais plus des petits trous de temps en temps. Petit trous qui défoncent le son et rendent inintéligible les paroles. L'idée est d'avoir de la redondance sur un ensemble de paquets (et donc un léger surpoid), qui sera utilisé pour reconstruire un paquet manquant. Le débit d'un flux audio étant bien plus faible qu'un flux vidéo, le surpoid de RED sera insignifiant. En revanche, les dégats causés par une perte de paquets sur le son sont bien pires que sur la vidéo (personne s'énerve sur une image figée). Ce choix semble pragmatique, à tester dès que ça sort.
AV1
Conçu au début pour être un équivalent libre de H.265, et comme successeur de VP8, AV1 apporte des gains en qualité conséquents. Utilisé depuis 2018 pour les vidéos préparés (Youtube, Vimeo, Netflix et compagnie) avec des améliorations récentes sur les temps de compression, Google le déploie maintenant pour du temps réel, et annonce un gain de 30% en qualité sur les petites connexions. A voir donc si le compromis CPU/débit sera pertinent sur toutes les machines.
Par contre, AV1 prévoit dans son format le SVC, et surtout le chiffrage de bout en bout, un des serpents de mer de WebRTC. Un SFU serait capable de distribuer les paquets vidéos sans être capable de les lire.
SFrame
Pour l'instant, WebRTC utilise le protocole DTLS avec une clef négociée pour chaque session dans le SDP. Le SFU participe à l'établissement de la session, il va donc connaitre la clef et sera capable de lire le contenu.
L'objectif est d'avoir du chiffrement de bout en bout, et donc d'avoir un SFU incapable de lire le contenu, et qui se contentera des headers pour prendre ses décisions de routage.
Les travaux experimentaux sur les Insertable Streams semble se normaliser avec les SFrame . Le chiffrement se fait sur les frames, et non les paquets RTP(ça alourdirait les headers de manière déraisonnable). A priori, seul les keyframes seraient chiffrées et non les frames intermédiaires, ce qui affiche une belle purée de pixel si on n'a pas la clef.
Utilisation
Qualité
WebRTC, avec ses contraintes de latence, et son ambition d'envoyer des flots trop gros (comme les partages d'écrans) navigue sur une contradiction. Pour un humain, une image floue ou qui saccade est décevante, mais un son qui coupe ("je passe dans un tunnel") est juste horrible. WebRTC se joue souvent à plusieurs, et être le pouilleux du groupe qui est le seul à avoir des soucis est bien frustrant. Montrer sa tête de mal réveillé, avec son expression corporelle prête à vous trahir, dans sa maison mal rangée, ajoute encore à la pression.
WebRTC est un challenge pour l'UX.
La qualité d'un échange en webrtc est séquentielle.
- Bande passante du serveur
- Accès Internet des clients
- Gestion des congestions
- Une UI pour emballer tout ça
La bande passante du serveur ne devrait pas poser de soucis, ne vous fiez pas aux sites de démos ou massivement mutualisés, une installation dédiée à vos besoins pourra être satisfaisante.
Les utilisateurs doivent avoir une connexion correcte à Internet, évitez donc la conccurence aux flux Webrtc pendant une conférence (pas de bitorrent cela va sans dire !).
Utiliser une compression maximale pour diminuer la taille des médias, mais sans pour autant écrouler la machine, ni la faire souffler comme au cap Horn.
La gestion des congestions, souvent assumée par le SFU, permettra de changer de résolution, de savoir quels paquets sacrifier pour qu'en face on puisse reconstituer le média avec une qualité dégradée, mais utilisable. Il ya beaucoup de magie pour cette étape, avec des trucs non spécifiés, non libre, et beaucoup de lobbying comme le relate cet article de Mozilla .
L'UI a une part cruciale dans le ressenti qu'auront les utilisateurs de l'application. Il doit être possible de connaître l'état et le statut des participants avec un indice clair si un interlocuteur parle, galère ou si les micros sont coupés. Le tchat en mode texte, pour dire que ça ne marche pas, ou pour envoyer une URL est indispensable. L'UI doit permettre d'éviter que tout soit allumé à fond tout le temps. Le grand classique est d'avoir une notion de prise de parole avec une personne intervenante qui occupe une majorité de l'écran, les autres s'affichent en petit, pour avoir les expressions faciales et bâillements. Les émojis ou la possibilité de lever la main peuvent aussi être utiles. Pour des grosses réunions, il ne sera plus possible que chaque personne puisse interagir en multimédia à n'importe quel moment.
Il n'existe pas d'application universelle et ultime, il ne faut pas hésiter à utiliser plusieurs applications adaptées, une fois le problème de l'authentification résolu.
Côté serveur
Les navigateurs webs ont rapidement intégré la stack WebRTC : https://caniuse.com/?search=webrtc . Microsoft a fait le malin en implémentant une variante avec un ORTC pour Edge et Skype, un presque webrtc orienté objet, qui n'utilise pas SDP.
Par contre, pour avoir du code qui fait du webrtc, c'est de suite beaucoup plus exotique. Les bibliothèques C pour chacune des briques existent depuis longtemps, et des bindings sont disponibles. Par contre, c'est compliqué de proposer une offre cohérente et complète, adaptée aux différents langages. Certains se permettent de recoder les couches basses (réseaux, protocole multimédia, etc.) mais pour les codecs vidéos, les optimisations sont agressives, avec de l'assembleur et des instructions spécifiques.
L'approche que l'on trouve le plus souvent est un service écrit en C ou C++, avec une API distante, du JSON sur une websocket, et des scripts satellites. Il existe aussi de vraies bibliothèques avec un binding officiel et une intégration dans la boucle évènementielle du langage.
Des audacieux ( Pion ) se sont lancés dans la réécriture dans un langage intermédiaire, du go en l'occurrence, permettant une intégration plus fine pour les applications, et surtout une plus grande facilité pour contribuer au coeur de l'application.
Services satellites
WebRTC dépends clairement de STUN/TURN, et c'est souvent cette partie, si vous ne la maitrisez pas qui va péter votre déploiement.
RTP utilise de l'UDP et va ouvrir un port par client, ce qui est surprenant pour les habitués du TCP, et globalement, les passerelles, que ce soit les réseaux privés d'EC2 ou ceux de Docker ne vont pas forcément aimer cette orgie de ports ouverts. De toute façon, les clients non NATés sont très rares.
TURN permet de sortir cette histoire de ports et de routage de l'application, qui pourra tourner dans un conteneur comme tout le monde.
Le besoin de serveurs TURN libres ne semble être apparu qu'avec l'arrivée de WebRTC. STUN est plus ancien, mais STUN tout seul, c'est triste, il faut du TURN/STUN. Pour l'instant, l'offre est anémique, il y a pion-turn et coturn .
Coturn
coturn est LE serveur STUN/TURN que l'on retrouve dans toutes les documentations. Il est beau et implémente tout ce qu'il trouve comme specs liées à STUN et TURN. Il invente même des trucs hors spec, comme l'authentification signée temporaire.
Aller plus loin
Là, on a fait une passe sur l'aspect théorique de WebRTC, dans le prochain épisode, on verra les produits existants.
Pour patienter, vous pouvez aller faire un tour sur le blog du Dr Alex ou mettre la capuche de votre hoody pour lire WebRTCHacks .
C'est bon, vous arrivez à comprendre ce que vous raconte votre about:webrtc
sur Firefox et chrome://webrtc-internals/
sur Chromium ?