{"id":16723,"date":"2018-05-02T14:52:34","date_gmt":"2018-05-02T18:52:34","guid":{"rendered":"https:\/\/www.crim.ca\/?post_type=blogue&#038;p=16723"},"modified":"2023-06-07T16:43:10","modified_gmt":"2023-06-07T20:43:10","slug":"webrtc-et-la-construction-dune-application-web-de-videoconference","status":"publish","type":"blogue","link":"https:\/\/www.crim.ca\/fr\/blogue\/webrtc-et-la-construction-dune-application-web-de-videoconference\/","title":{"rendered":"WebRTC et la construction d\u2019une application Web de vid\u00e9oconf\u00e9rence"},"content":{"rendered":"<div class=\"iw ix iy iz ja\">\n<p data-selectable-paragraph=\"\">Ce billet repr\u00e9sente le fruit d\u2019une veille technologique pr\u00e9alable \u00e0 la construction d\u2019une application Web de vid\u00e9oconf\u00e9rence bas\u00e9e sur une architecture moderne et utilisant les technologies disponibles en ce printemps 2018.<\/p>\n<p id=\"c4d1\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Nous entendons par \u00abapplications Web\u00bb une application ne n\u00e9cessitant aucune installation suppl\u00e9mentaire et respectant les derniers standards Web recommand\u00e9s par le W3C. Cela exclut donc, par exemple, une technologie n\u00e9cessitant l\u2019installation d\u2019un\u00a0<em class=\"ky\">plugin\u00a0<\/em>Flash dans le navigateur.<\/p>\n<p id=\"8b69\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Ceci est l\u2019histoire, plut\u00f4t technique mais tout de m\u00eame accessible, d\u2019une petite aventure dans l\u2019univers WebRTC de la vid\u00e9oconf\u00e9rence Web.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu kz\"><img fetchpriority=\"high\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1380\/0*TFX7T5zTfvoMPX4s.png\" alt=\"\" width=\"690\" height=\"300\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Source:\u00a0<a class=\"au lk\" href=\"https:\/\/www.pubnub.com\/wp-content\/uploads\/2014\/10\/WebRTCVoice.png\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/www.pubnub.com\/wp-content\/uploads\/2014\/10\/WebRTCVoice.png<\/a><\/figcaption><\/figure>\n<h2 id=\"00fe\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">Les protocoles de diffusion vid\u00e9o<\/h2>\n<p id=\"fcf5\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Nos premi\u00e8res recherches nous ont rapidement amen\u00e9s vers les protocoles de diffusion vid\u00e9o et la notion de diffusion en direct (<em class=\"ky\">live streaming)<\/em>. Apr\u00e8s tout, ne cherchions-nous pas nous aussi \u00e0 partager en direct du contenu audio\/vid\u00e9o dans un lecteur vid\u00e9o HTML5?<\/p>\n<blockquote class=\"mo mp mq\">\n<p id=\"6fa4\" class=\"ka kb ky kc b kd ke kf kg kh ki kj kk mr km kn ko ms kq kr ks mt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">Note<\/strong>. Pour un tour d\u2019horizon de ces technologies, voir ce rapport encore tout \u00e0 fait pertinent:\u00a0<a class=\"au lk\" href=\"https:\/\/www.crim.ca\/fr\/component\/publications\/etat-de-l-art-des-technologies-et-protocoles-de-diffusion-de-contenu-video-sur-internet\" target=\"_blank\" rel=\"noopener ugc nofollow\">\u00c9tat de l\u2019art des technologies et protocoles de diffusion de contenu vid\u00e9o sur Internet<\/a><\/p>\n<\/blockquote>\n<p id=\"7ddd\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Les protocoles\u00a0<strong class=\"kc je\">HLS\u00a0<\/strong>(pour HTTP Live Streaming),\u00a0<strong class=\"kc je\">MPEG-DASH<\/strong>\u00a0(Dynamic Adaptative Streaming over HTTP) ou encore\u00a0<strong class=\"kc je\">HDS\u00a0<\/strong>(HTTP Dynamic Streaming) existent pour accomplir cette t\u00e2che. Le d\u00e9bat est encore en cours \u00e0 savoir lequel s\u00e9lectionner pour une diffusion en direct de contenu vid\u00e9o.<\/p>\n<p id=\"9608\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">En r\u00e9alit\u00e9, bien qu\u2019on parle de diffusion en direct, ces protocoles impliquent une\u00a0<strong class=\"kc je\">latence de niveau interm\u00e9diaire<\/strong>\u00a0puisqu\u2019ils sont tous bas\u00e9s sur HTTP, lui-m\u00eame bas\u00e9 sur TCP\/IP. Avec HLS ou MPEG-DASH, par exemple, on aura un \u00e9cart de l\u2019ordre de 30 \u00e0 45 secondes entre la captation du flux multim\u00e9dia et l\u2019\u00e9coute de celui-ci dans le navigateur! Cet \u00e9cart pourrait \u00eatre \u00e9ventuellement r\u00e9duit sous les 10 secondes en utilisant diff\u00e9rentes techniques d\u2019optimisation (voir<em class=\"ky\">\u00a0<\/em><a class=\"au lk\" href=\"https:\/\/medium.com\/@eyevinntechnology\/achieving-low-latency-video-streaming-b0b806dcc282\" rel=\"noopener\">Achieving low latency video streaming<\/a>).<\/p>\n<blockquote class=\"mo mp mq\">\n<p id=\"54ad\" class=\"ka kb ky kc b kd ke kf kg kh ki kj kk mr km kn ko ms kq kr ks mt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">Note<\/strong>. Il existe aussi d\u2019autres protocoles comme\u00a0<strong class=\"kc je\">RTMP\u00a0<\/strong>qui n\u2019est pas bas\u00e9 sur HTTP et offre une faible latence, mais qui n\u00e9cessite un plugin Flash pour \u00eatre utilis\u00e9 dans un navigateur, ce qui l\u2019exclut d\u2019office.<\/p>\n<\/blockquote>\n<p id=\"dfbf\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Une latence de plusieurs secondes est, par ailleurs, inimaginable dans un contexte de vid\u00e9oconf\u00e9rence et c\u2019est pour cette raison qu\u2019il faut irr\u00e9m\u00e9diablement se tourner vers des diffusions \u00e0 ultra-faible latence, des\u00a0<strong class=\"kc je\">diffusions en temps r\u00e9el<\/strong>.<\/p>\n<p id=\"8ae5\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Au-del\u00e0 de la latence, la diffusion en direct est un cas d\u2019utilisation distinct du n\u00f4tre en ce qu\u2019elle est, par nature,\u00a0<strong class=\"kc je\">unidirectionnelle\u00a0<\/strong>et implique souvent la diffusion \u00e0\u00a0<strong class=\"kc je\">une large audience<\/strong>\u2026 Bon, il s\u2019agit certainement d\u2019un mauvais d\u00e9part et vous \u00eates probablement aussi confus que nous\u2026<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu mu\"><img decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*JoEunezTwDM_Ksch9VAwKg.jpeg\" alt=\"\" width=\"700\" height=\"467\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"4d66\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Et si on prenait un peu de recul pour mieux comprendre les enjeux?<\/p>\n<h2 id=\"4178\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">Communication temps-r\u00e9el dans le navigateur<\/h2>\n<p id=\"08e1\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Dans un monde pas si lointain, toute fonctionnalit\u00e9 interactive ou encore tout traitement intensif c\u00f4t\u00e9 client dans un navigateur passaient par l\u2019interm\u00e9diaire de\u00a0<em class=\"ky\">plugins:\u00a0<\/em>Java Applet ou encore Flash (particuli\u00e8rement pour l\u2019affichage de contenu vid\u00e9o). Ces\u00a0<em class=\"ky\">plugins\u00a0<\/em>\u00e9taient aussi un mal n\u00e9cessaire pour pouvoir utiliser les diff\u00e9rents protocoles de communication ou autres standards propres au monde de l\u2019Internet.<\/p>\n<p id=\"43e8\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Dans le monde plus particulier de la communication temps-r\u00e9el, hier encore, l\u2019installation d\u2019un logiciel propri\u00e9taire (WebEx, Zoom) \u00e9tait n\u00e9cessaire pour initier une communication multim\u00e9dia en temps r\u00e9el. Dans le monde du Web, le\u00a0<em class=\"ky\">plugin\u00a0<\/em>Flash permit de rem\u00e9dier temporairement \u00e0 cette situation en offrant l\u2019interop\u00e9rabilit\u00e9 dont tous r\u00eavaient et en \u00e9largissant les possibilit\u00e9s permises dans le navigateur Web. Mais Flash appartenait \u00e0 une seule compagnie, son d\u00e9veloppement n\u2019\u00e9tait ni concert\u00e9 ni ouvert et cette technologie op\u00e9rait dans un navigateur Web, tel un corps \u00e9tranger, par interm\u00e9diaire de l\u2019installation d\u2019un\u00a0<em class=\"ky\">plugin.<\/em><\/p>\n<p id=\"1214\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Or, depuis l\u2019av\u00e8nement du standard HTML5, l\u2019id\u00e9e, et la tendance g\u00e9n\u00e9rale, est d\u2019apporter les fonctionnalit\u00e9s directement dans le navigateur et d\u2019instaurer des API r\u00e9ellement\u00a0<strong class=\"kc je\">natives (<\/strong>du point de vue du navigateur)<strong class=\"kc je\">\u00a0<\/strong>et d\u00e9velopp\u00e9es de fa\u00e7on collaborative et\u00a0<strong class=\"kc je\">ouverte\u00a0<\/strong>par les acteurs de l\u2019industrie.<\/p>\n<p id=\"1354\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Ainsi naquit la\u00a0<a class=\"au lk\" href=\"https:\/\/www.w3.org\/TR\/webrtc\" target=\"_blank\" rel=\"noopener ugc nofollow\">sp\u00e9cification WebRTC<\/a><\/p>\n<h2 id=\"1f93\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">La sp\u00e9cification WebRTC<\/h2>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu mz\"><img decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*zowNpUJSA1OmsscHvlMc8w.jpeg\" alt=\"\" width=\"700\" height=\"467\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"a4ce\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">WebRTC pour\u00a0<strong class=\"kc je\">Web Real-Time Communication<\/strong>\u00a0entend, comme son nom l\u2019indique, rendre possible les communications multim\u00e9dias en temps r\u00e9el dans un contexte Web en \u00e9vacuant la n\u00e9cessit\u00e9 d\u2019une installation pr\u00e9alable. WebRTC est une collection de standards, de protocoles et d\u2019API JavaScript permettant le partage navigateur \u00e0 navigateur de contenu vid\u00e9o, audio ou encore de donn\u00e9es.<\/p>\n<p id=\"5b60\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Ce standard fut d\u00e9fini conjointement par le\u00a0<a class=\"au lk\" href=\"https:\/\/www.w3.org\/Consortium\/activities#Web_Real-Time_Communications_Working_Group\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"kc je\">W3C Working Group<\/strong><\/a><strong class=\"kc je\">,<\/strong>\u00a0qui se chargea de la d\u00e9finition des API dans le navigateur, et l\u2019<a class=\"au lk\" href=\"https:\/\/tools.ietf.org\/wg\/rtcweb\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"kc je\">IETF Working Group<\/strong><\/a><strong class=\"kc je\">,<\/strong>\u00a0qui s\u2019occupa des aspects plus techniques des protocoles d\u2019\u00e9change, du format des donn\u00e9es, de la s\u00e9curit\u00e9, etc.<\/p>\n<p id=\"9652\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">WebRTC se compose de trois API principales \u2014 MediaStream, RTCPeerConnection, DataChannel \u2014 et n\u00e9cessite quelques protocoles de transport que nous verrons dans cette section.<\/p>\n<h2 id=\"8de7\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">MediaStream<\/h2>\n<p id=\"079d\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Un crit\u00e8re essentiel pour que le navigateur puisse offrir des fonctionnalit\u00e9s de t\u00e9l\u00e9conf\u00e9rence est \u00e9videmment de pouvoir acc\u00e9der au contenu audio\/vid\u00e9o captur\u00e9 par l\u2019appareil h\u00f4te.<\/p>\n<p id=\"6c7e\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">L\u2019objet MediaStream permet un tel acc\u00e8s simplifi\u00e9 par la m\u00e9thode\u00a0<strong class=\"kc je\">getUserMedia<\/strong>, mais encapsule aussi de puissants moteurs de traitement audio\/vid\u00e9o internes permettant d\u2019en am\u00e9liorer la qualit\u00e9 (encodage, d\u00e9codage, synchronisation, gestion des fluctuations de la bande passante, dissimulation des paquets perdus, r\u00e9duction des bruits dans la bande audio, am\u00e9lioration de l\u2019image dans le flux vid\u00e9o, etc.) Notons que la majorit\u00e9 des navigateurs vont forcer l\u2019utilisation de HTTPS dans la page avant de permettre l\u2019utilisation de getUserMedia.<\/p>\n<p id=\"4322\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">WebRTC supporte pr\u00e9sentement diff\u00e9rents codecs de compression, mais principalement\u00a0<strong class=\"kc je\">VP8\u00a0<\/strong>et\u00a0<strong class=\"kc je\">H.264<\/strong>\u00a0pour la vid\u00e9o et\u00a0<strong class=\"kc je\">Opus\u00a0<\/strong>pour l\u2019audio.<\/p>\n<p id=\"4778\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Une fois l\u2019acquisition du flux multim\u00e9dia enclench\u00e9, celui-ci peut \u00eatre utilis\u00e9 \u00e0 diff\u00e9rentes fins dans d\u2019autres API du navigateur:\u00a0<strong class=\"kc je\">Web Audio<\/strong>\u00a0pour lancer la piste audio dans le navigateur,\u00a0<strong class=\"kc je\">Canvas<\/strong>\u00a0pour faire la capture d\u2019une image,\u00a0<strong class=\"kc je\">CSS3<\/strong>\u00a0et\u00a0<strong class=\"kc je\">WebGL<\/strong>\u00a0pour appliquer des effets 2D\/3D sur le flux ou encore\u00a0<strong class=\"kc je\">RTCPeerConnection,<\/strong>\u00a0que nous verrons plus loin, pour envoyer directement ces donn\u00e9es \u00e0 un autre navigateur!<\/p>\n<h2 id=\"5d2b\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Transport et protocoles<\/h2>\n<p id=\"c0a4\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">WebRTC se distingue d\u2019abord par le choix du protocole de transport qui le soutient. En effet, WebRTC a d\u00e9termin\u00e9\u00a0<strong class=\"kc je\">UDP\u00a0<\/strong>comme couche de transport (du mod\u00e8le OSI) qui se pr\u00eate particuli\u00e8rement bien au contexte temps-r\u00e9el o\u00f9 la latence devient critique. Si UDP n\u2019offre aucune garantie par rapport \u00e0 TCP (qui garantit l\u2019arriv\u00e9e des paquets, mais aussi l\u2019ordre de ceux-ci), il se pr\u00eate beaucoup mieux aux flux multim\u00e9dias en temps r\u00e9el qui peuvent g\u00e9n\u00e9ralement supporter la perte de certaines donn\u00e9es (codecs audio et vid\u00e9o).<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu no\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1308\/1*FAG1g--_yhngJ2JzeUHRwg.png\" alt=\"\" width=\"654\" height=\"322\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Protocoles du Web \u00e0 gauche et WebRTC \u00e0 droite. Source:\u00a0<a class=\"au lk\" href=\"https:\/\/hpbn.co\/assets\/diagrams\/f91164cbbb944d8986c90a1e93afcd82.svg\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/hpbn.co\/assets\/diagrams\/f91164cbbb944d8986c90a1e93afcd82.svg<\/a><\/figcaption><\/figure>\n<p id=\"3d4d\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Comme le diagramme pr\u00e9c\u00e9dant en t\u00e9moigne, d\u2019autres protocoles sont mis en oeuvre pour permettre notamment le cryptage du contenu, mais aussi le contr\u00f4le du d\u00e9bit, le contr\u00f4le de la congestion, la gestion des erreurs, etc., tous n\u00e9cessaires pour \u00e9viter la submersion du r\u00e9seau et la d\u00e9gradation de la communication:<\/p>\n<ul class=\"\">\n<li id=\"4701\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">DLTS\u00a0<\/strong>est utilis\u00e9 comme couche obligatoire de s\u00e9curit\u00e9 et de cryptage<\/li>\n<li id=\"9012\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">SRTP\u00a0<\/strong>est le protocole utilis\u00e9 pour le transport des flux audio\/vid\u00e9o<\/li>\n<li id=\"b06a\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">SCTP\u00a0<\/strong>est utilis\u00e9 comme transport des autres donn\u00e9es applicatives<\/li>\n<\/ul>\n<p id=\"8327\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Enfin, nous expliquerons plus en d\u00e9tail plus tard la signification de la couche\u00a0<strong class=\"kc je\">ICE\/STUN\/TURN<\/strong>\u00a0qui m\u00e9rite d\u2019\u00eatre approfondie.<\/p>\n<h2 id=\"e4b1\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">DataChannel<\/h2>\n<p id=\"ce89\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Cette API permet l\u2019\u00e9change de donn\u00e9es arbitraires (textuelles ou binaires) entre navigateurs et est enti\u00e8rement d\u00e9pendante de l\u2019objet RTCPeerConnection en ce qu\u2019elle n\u00e9cessite une connexion d\u00e9j\u00e0 ouverte. C\u2019est r\u00e9ellement l\u2019\u00e9quivalent de WebSocket, mais cette fois-ci entre deux pairs et \u00e0 quelques diff\u00e9rences pr\u00e8s: la session d\u2019\u00e9change peut \u00eatre initi\u00e9e par l\u2019une ou l\u2019autre des parties prenantes et la m\u00e9thode de livraison des paquets et la fiabilit\u00e9 de celle-ci est configurable (au moyen de SCTP).<\/p>\n<h2 id=\"ad34\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">RTCPeerConnection<\/h2>\n<p id=\"63ba\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">L\u2019API RTCPeerConnection est responsable de la communication des contenus audio et vid\u00e9o et devient donc fondamentale dans le cas qui nous int\u00e9resse. C\u2019est par cette interface que deux pairs vont apprendre \u00e0 communiquer ensemble et vont \u00e9tablir un tunnel de partage de contenu multim\u00e9dia (par SRTP).<\/p>\n<p id=\"dac8\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">RTCPeerConnection s\u2019occupe des \u00e9tapes d\u2019initialisation de la connexion entre les pairs, la gestion de la session, l\u2019envoi des flux multim\u00e9dias et l\u2019\u00e9tat de la communication.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu od\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*RGnhBTJ2b5H_ewVnGFzK7Q.png\" alt=\"\" width=\"700\" height=\"105\" \/><\/div>\n<\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Connexion pair \u00e0 pair de partage de contenu multim\u00e9dia. Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures: A Guide to WebRTC \u2014 How it works Part I<\/a><\/figcaption><\/figure>\n<h2 id=\"619c\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">L\u2018initialisation de la communication: la pi\u00e8ce manquante<\/h2>\n<p id=\"8aac\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Malheureusement, la connexion de deux pairs par l\u2019interm\u00e9diaire d\u2019un navigateur n\u2019est pas aussi simple que notre dernier graphique le laisse entendre. Quelques \u00e9tapes sont encore n\u00e9cessaires tels que l\u2019initialisation d\u2019une telle connexion!<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu oe\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*apWXeH4DriEwQoiYA14BTg.jpeg\" alt=\"\" width=\"700\" height=\"408\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"3015\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Volontairement exclue de la sp\u00e9cification WebRTC, l\u2019initialisation de la communication (ou\u00a0<em class=\"ky\">signaling<\/em>) est le cha\u00eenon manquant sans lequel vos fureteurs ne pourront pas communiquer directement ensemble. Cette initialisation n\u00e9cessaire \u00e0 RTCPeerConnection requiert imp\u00e9rativement un serveur distant qui va servir d\u2019interm\u00e9diaire aux diff\u00e9rents participants. L\u2019initialisation se r\u00e9sume \u00e0 l\u2019authentification des participants et \u00e0 l\u2019\u00e9change d\u2019informations n\u00e9cessaires \u00e0 la localisation des multiples participants (adresse IP, port, SDP local, etc.).<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu of\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1394\/1*eidr8F2l5hhAmc931UDiHA.png\" alt=\"\" width=\"697\" height=\"358\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">L\u2019initialisation comme l\u2019une des trois \u00e9tapes essentielles. Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures: How-to build a video conference application using webRTC<\/a><\/figcaption><\/figure>\n<ol class=\"\">\n<li id=\"5935\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx og nv nw nx gi\" data-selectable-paragraph=\"\">Le navigateur obtient l\u2019acc\u00e8s au mat\u00e9riel d\u2019enregistrement comme la cam\u00e9ra ou le microphone.<\/li>\n<li id=\"8b73\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx og nv nw nx gi\" data-selectable-paragraph=\"\">Chaque participant s\u2019identifie et \u00e9change l\u2019information n\u00e9cessaire \u00e0 l\u2019\u00e9tablissement d\u2019une connexion avec les autres participants.<\/li>\n<li id=\"ecc1\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx og nv nw nx gi\" data-selectable-paragraph=\"\">Chaque participant peut maintenant partager directement son contenu multim\u00e9dia avec les autres participants et la communication peut alors commencer.<\/li>\n<\/ol>\n<p id=\"e241\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">\u00c9tant exclus de la sp\u00e9cification, plusieurs protocoles concurrents d\u2019initialisation sont utilis\u00e9s dans le contexte WebRTC tel que SIP, XMPP, Socket.IO ou encore diff\u00e9rents protocoles personnalis\u00e9s et\/ou propri\u00e9taires (les fournisseurs de PaaS par exemple). Si WebSocket est g\u00e9n\u00e9ralement utilis\u00e9 comme transport pour ces protocoles (de par sa nature bidirectionnelle) d\u2019autres m\u00e9thodes peuvent aussi \u00eatre utilis\u00e9es comme XHR\/Comet, SSE, HTTP\/2 ou encore la fameuse ficelle pour les plus nostalgiques.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu oh\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*e_gg7xGW62t7dSn_WY5Bvw.jpeg\" alt=\"\" width=\"700\" height=\"467\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"d8ca\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Une pluralit\u00e9 de solutions existe donc pour l\u2019initialisation et ces solutions sont plut\u00f4t \u00e9quivalentes ou ne repr\u00e9sentent pas n\u00e9cessairement un grand enjeu. Une fois l\u2019initialisation compl\u00e9t\u00e9e, le serveur interm\u00e9diaire ne sera th\u00e9oriquement plus requis pour la suite de la communication.<\/p>\n<p id=\"0882\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Si on peut croire que la communication pourrait enfin avoir lieu, d\u00e9trompez-vous, le r\u00e9seau Internet entend nous offrir encore quelques surprises\u2026<\/p>\n<h2 id=\"8c6e\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">La r\u00e9alit\u00e9 du monde d\u2019Internet et les serveurs ICE (STUN\/TURN)<\/h2>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu oi\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*ELtxFJwpxw-5PB1yO9p-vQ.jpeg\" alt=\"\" width=\"700\" height=\"467\" \/><\/div>\n<\/div>\n<\/figure>\n<p id=\"cae1\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Le r\u00e9seau Internet est en fait constitu\u00e9 de plusieurs millions de r\u00e9seaux publics et priv\u00e9s reli\u00e9s par de nombreux c\u00e2bles, routeurs et une panoplie d\u2019autres dispositifs comme des pare-feu ou encore des routeurs NAT (Network Address Translation) ainsi que diff\u00e9rentes restrictions d\u00e9termin\u00e9es par votre fournisseur de service Internet (ISP).<\/p>\n<p id=\"e4af\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">La majorit\u00e9 des appareils disposent d\u2019une adresse IP priv\u00e9e (adresse non unique d\u2019un point de vue global) et n\u00e9cessite un dispositif NAT qui s\u2019occupe de transformer l\u2019adresse priv\u00e9e en adresse publique (ainsi que les ports) pour pouvoir acc\u00e9der \u00e0 l\u2019Internet. En r\u00e9alit\u00e9, dans la grande majorit\u00e9 des cas, deux fureteurs ne pourront tout simplement pas communiquer directement ensemble puisqu\u2019aucun des deux ne conna\u00eet l\u2019adresse IP et le port qu\u2019il peut utiliser pour atteindre l\u2019autre.<\/p>\n<p id=\"15c6\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">C\u2019est ici que la technique\u00a0<strong class=\"kc je\">ICE\u00a0<\/strong>(Interactive Connectivity Establishment) intervient pour permettre aux agents WebRTC de communiquer en faisant abstraction de la complexit\u00e9 des r\u00e9seaux formant la r\u00e9alit\u00e9 d\u2019Internet. ICE va utiliser des serveurs Session Traversal Utilities for NAT (STUN) et Traversal Using Relays around NAT (TURN) pour palier aux probl\u00e8mes caus\u00e9s par les pare-feu, les routeurs NAT et autres restrictions potentielles.<\/p>\n<p id=\"07ca\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Un serveur\u00a0<strong class=\"kc je\">STUN\u00a0<\/strong>permet \u00e0 l\u2019agent de conna\u00eetre les informations r\u00e9seaux qu\u2019il expose \u00e0 l\u2019externe, soit son adresse IP publique, le port, mais aussi le type de routeur NAT devant lui. Un tel serveur est en quelque sorte l\u2019\u00e9quivalent du site Web bien connu\u00a0<a class=\"au lk\" href=\"https:\/\/www.whatismyip.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/www.whatismyip.com\/<\/a>.<\/p>\n<p id=\"9f5b\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Un serveur\u00a0<strong class=\"kc je\">TURN\u00a0<\/strong>est une extension \u00e0 STUN lorsque celui-ci ne parvient pas \u00e0 \u00e9tablir la connexion. Il va permettre de relayer le m\u00e9dia d\u2019un agent \u00e0 l\u2019autre et devra \u00eatre pr\u00e9sent durant toute la communication contrairement \u00e0 STUN. TURN est une op\u00e9ration d\u00e9finitivement plus exigeante et la communication directe devrait en tout temps \u00eatre privil\u00e9gi\u00e9e.<\/p>\n<p id=\"0513\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">En r\u00e9alit\u00e9, ICE fait partie int\u00e9grante de l\u2019\u00e9tape d\u2019initialisation de la communication et voici \u00e0 quoi ressemble notre nouvelle architecture apr\u00e8s avoir ajout\u00e9 nos serveurs STUN et TURN:<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu oj\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1264\/1*eHz4SJtoD0R07_NVdX_SMg.png\" alt=\"\" width=\"632\" height=\"416\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Architecture WebRTC avec serveurs TURN et STUN. Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures: A Guide to WebRTC How it works Part I<\/a><\/figcaption><\/figure>\n<p id=\"7375\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Diff\u00e9rents niveaux de solutions s\u2019offrent \u00e0 vous pour l\u2019utilisation des serveurs STUN\/TURN \u00e0 savoir:<\/p>\n<ul class=\"\">\n<li id=\"0d8c\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Utiliser des serveurs gratuits sur lesquels vous n\u2019aurez aucun contr\u00f4le (<a class=\"au lk\" href=\"https:\/\/gist.github.com\/yetithefoot\/7592580\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/gist.github.com\/yetithefoot\/7592580<\/a>\u00a0pour une liste succincte)<\/li>\n<li id=\"083b\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Souscrire \u00e0 un service payant (Twilio, etc.)<\/li>\n<li id=\"a9c3\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Cr\u00e9er votre propre serveur en utilisant par exemple une solution\u00a0<em class=\"ky\">open source<\/em>\u00a0comme coturn (<a class=\"au lk\" href=\"https:\/\/github.com\/coturn\/coturn\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/github.com\/coturn\/coturn<\/a>) ou autre<\/li>\n<\/ul>\n<h2 id=\"0fd8\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">La nature pluripartite d\u2019une vid\u00e9oconf\u00e9rence<\/h2>\n<p id=\"ce33\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Jusqu\u2019\u00e0 maintenant nous avons vu comment connecter un pair \u00e0 un autre, mais qu\u2018arrive-t-il lorsque que nous voulons connecter plus de participants comme dans le cas d\u2019une vid\u00e9oconf\u00e9rence typique? Il existe en fait trois approches pour d\u00e9ployer une application de vid\u00e9oconf\u00e9rence pluripartite: Mesh, MCU et SFU.<\/p>\n<h2 id=\"c2f9\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">L\u2019approche Mesh<\/h2>\n<p id=\"83ce\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Mesh est en quelque sorte l\u2019approche na\u00efve, \u00e0 savoir que chaque participant va envoyer son m\u00e9dia \u00e0 chacun des autres participants. Cette approche \u00e9choue rapidement au del\u00e0 de 3 participants en termes de bande passante et de nombre de connexions. Un participant devra t\u00e9l\u00e9verser son m\u00e9dia \u00e0 chacun des autres participants et t\u00e9l\u00e9charger le m\u00e9dia de chacun de ceux-ci.<\/p>\n<p id=\"c813\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">C\u2019est cette approche qui est mise en oeuvre dans la plupart des tutoriels WebRTC disponibles un peu partout sur la toile. Il s\u2019agit d\u2019une excellente preuve de concept, mais peu applicable \u00e0 un contexte de production \u00e0 moins d\u2019en conna\u00eetre express\u00e9ment les limites.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu ok\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/932\/1*IpobtimGsZXfInva-y7wfQ.png\" alt=\"\" width=\"466\" height=\"296\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Mod\u00e8le Mesh. Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures A Guide to WebRTC \u2014 How it works Part II<\/a><\/figcaption><\/figure>\n<h2 id=\"2ea1\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Le mod\u00e8le MCU<\/h2>\n<p id=\"6e3b\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">MCU pour Multiparting Conferencing Unit est l\u2019approche dans laquelle les diff\u00e9rents participants vont tous communiquer avec une unit\u00e9 centrale (un serveur) qui va s\u2019occuper de\u00a0<em class=\"ky\">mixer<\/em>\u00a0ou composer<em class=\"ky\">\u00a0<\/em>les diff\u00e9rents flux en un seul flux audio-vid\u00e9o (en fait, quelques gabarits, mais un seul sera envoy\u00e9 aux participants). C\u2019est d\u00e9finitivement la meilleure approche en terme de charge sur le r\u00e9seau et de nombre de connexions. Cette approche limite \u00e0 une connexion entrante et sortante entre le client et le serveur, peu importe le nombre de participants.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu ok\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/932\/1*Tr155Zi8_6nsiVy2EJD5vw.png\" alt=\"\" width=\"466\" height=\"293\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Mod\u00e8le Multiparting Conferencing Unit (MCU). Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures A Guide to WebRTC \u2014 How it works Part II<\/a><\/figcaption><\/figure>\n<h2 id=\"40db\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">L\u2019approche SFU<\/h2>\n<p id=\"af3b\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Par ailleurs, la troisi\u00e8me approche SFU (pour Selective Forwarding Unit) propose que chaque participant envoie son m\u00e9dia \u00e0 un serveur central qui s\u2019occupe de le rediriger (<em class=\"ky\">router)\u00a0<\/em>aux autres participants si ceux-ci en font la demande. On limite ainsi \u00e0 un le nombre de t\u00e9l\u00e9versement par rapport \u00e0 Mesh (n participants), mais on garde le nombre de t\u00e9l\u00e9chargements de flux \u00e9gal au nombre de participants.<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"gt gu ol\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/860\/1*nVasdU2mde3Tz0vnzaUPew.png\" alt=\"\" width=\"430\" height=\"335\" \/><\/div><figcaption class=\"lh bm gv gt gu li lj bn b bo bp co\" data-selectable-paragraph=\"\">Mod\u00e8le Selective Forwarding Unit (SFU). Source:\u00a0<a class=\"au lk\" href=\"https:\/\/webrtc.ventures\/2017\/11\/free-webrtc-training-tutorials-ecourse\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">WebRTC.ventures A Guide to WebRTC \u2014 How it works Part II<\/a><\/figcaption><\/figure>\n<h2 id=\"436d\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Choisir le bon mod\u00e8le pour votre cas d\u2019utilisation<\/h2>\n<p id=\"731a\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Si on peut croire que MCU est le mod\u00e8le le plus int\u00e9ressant, il faut savoir qu\u2019un tel serveur central doit s\u2019occuper de tous les traitements, \u00e0 savoir la\u00a0<strong class=\"kc je\">r\u00e9ception<\/strong>, le\u00a0<strong class=\"kc je\">d\u00e9codage\u00a0<\/strong>des flux, la\u00a0<strong class=\"kc je\">composition\u00a0<\/strong>du nouveau flux, le\u00a0<strong class=\"kc je\">r\u00e9encodage<\/strong>\u00a0des diff\u00e9rents flux et l\u2019<strong class=\"kc je\">envoi<\/strong>: tous des traitements extr\u00eamement exigeants c\u00f4t\u00e9 CPU. Plus la taille des flux vid\u00e9os augmentera (4k, mais bient\u00f4t 8k), plus ce temps de traitement cro\u00eetra largement avec cette approche et un d\u00e9ploiement \u00e0 grande \u00e9chelle bas\u00e9 sur le mod\u00e8le MCU demande des dizaines, voire des centaines de machines suppl\u00e9mentaires par rapport \u00e0 SFU.<\/p>\n<p id=\"de7a\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">En fait, c\u2019est l\u2019approche SFU qui est de plus en plus privil\u00e9gi\u00e9e dans le contexte WebRTC, quoique les diff\u00e9rentes solutions offrent souvent des mod\u00e8les hybrides. WebRTC \u00e9tant multi-flux par nature, le mod\u00e8le SFU s\u2019inscrit parfaitement dans cette logique: le client re\u00e7oit de multiples flux audio et vid\u00e9o qu\u2019il doit d\u00e9coder individuellement et afficher \u00e0 l\u2019\u00e9cran. SFU limite le serveur interm\u00e9diaire aux t\u00e2ches simples et peu exigeantes \u00e0 savoir la\u00a0<strong class=\"kc je\">r\u00e9ception<\/strong>, la\u00a0<strong class=\"kc je\">s\u00e9lection\u00a0<\/strong>et\u00a0<strong class=\"kc je\">l\u2019envoi\u00a0<\/strong>des flux.<\/p>\n<p id=\"900b\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">L\u2019approche SFU pure a le d\u00e9savantage d\u2019\u00eatre exigeante au niveau de la bande passante d\u2019un participant qui doit apr\u00e8s tout t\u00e9l\u00e9charger plusieurs flux. Ainsi, certaines approches SFU offrent parfois l\u2019encodage et le d\u00e9codage des contenus ne serait-ce que pour pouvoir offrir un contenu adapt\u00e9 aux participants (Adaptative Bitrate Streaming) et ainsi maximiser l\u2019exp\u00e9rience utilisateur en limitant les interruptions.<\/p>\n<p id=\"c72f\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">L\u2019autre option est d\u2019utiliser un codec supportant l\u2019extensibilit\u00e9 (H.264 SVC \/ Scalable VP9) ou le Simulcast pour b\u00e9n\u00e9ficier d\u2019une architecture purement SFU avec l\u2019adaptation de contenu. Dans un tel mod\u00e8le SFU, chaque participant se trouve \u00e0 t\u00e9l\u00e9verser un oignon de couches vid\u00e9o de diff\u00e9rentes qualit\u00e9s et le serveur d\u00e9cide laquelle de ces couches sera transmise \u00e0 quel participant (voir\u00a0<a class=\"au lk\" href=\"http:\/\/info.vidyo.com\/rs\/vidyo\/images\/WP-Vidyo-SVC-Video-Communications.pdf\" target=\"_blank\" rel=\"noopener ugc nofollow\">SVC and Video Communications<\/a>).<\/p>\n<p id=\"8687\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Si SFU demeure le mod\u00e8le privil\u00e9gi\u00e9 du fait de ses faibles co\u00fbts de d\u00e9ploiement et d\u2019exploitation par rapport \u00e0 MCU, chacun des trois mod\u00e8les r\u00e9pond ad\u00e9quatement \u00e0 diff\u00e9rents cas d\u2019utilisation. Par exemple, dans le cas de vid\u00e9oconf\u00e9rences se limitant \u00e0 3 voire 5 participants, le mod\u00e8le Mesh peut s\u2019av\u00e9rer parfaitement ad\u00e9quat. Dans un cas o\u00f9 les diff\u00e9rents clients sont mobiles et disposent de peu de ressources autant au niveau CPU que de la bande-passante, MCU s\u2019av\u00e8re l\u2019architecture optimale. Une approche hybride permet aussi de faire basculer l\u2019application d\u2019un mod\u00e8le de type Mesh, quand un nombre minimal de participants sont connect\u00e9s, \u00e0 MCU\/SFU lorsque le nombre passe au-del\u00e0 de 4 ou 5.<\/p>\n<h2 id=\"c35c\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">Autres fonctionnalit\u00e9s que vous voudrez ou non<\/h2>\n<p id=\"076b\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Au-del\u00e0 de la possibilit\u00e9 d\u2019avoir une infrastructure ayant la capacit\u00e9 de supporter des conf\u00e9rences de nature pluripartite, d\u2019autres fonctionnalit\u00e9s sont aussi int\u00e9ressantes et souvent disponibles dans les diff\u00e9rents produits que nous verrons plus loin, comme:<\/p>\n<ul class=\"\">\n<li id=\"5a98\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">L\u2019enregistrement des contenus audio et vid\u00e9o<\/li>\n<li id=\"1ef1\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Qualit\u00e9 du contenu vid\u00e9o adapt\u00e9 \u00e0 chaque participant<\/li>\n<li id=\"df8f\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Un syst\u00e8me de messagerie texte<\/li>\n<li id=\"59fb\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">La possibilit\u00e9 de pouvoir partager des fichiers<\/li>\n<li id=\"6e0a\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Le partage d\u2019\u00e9cran<\/li>\n<li id=\"76e3\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">La possibilit\u00e9 de pouvoir faire des dessins ou maquettes sous forme de\u00a0<em class=\"ky\">whiteboard\u00a0<\/em>en temps r\u00e9el<\/li>\n<li id=\"38d2\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">La r\u00e9alit\u00e9 augment\u00e9e (filtres, objets, etc.)<\/li>\n<li id=\"2766\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">L\u2019int\u00e9gration avec diff\u00e9rents protocoles d\u2019initialisation\u00a0<em class=\"ky\">legacy\u00a0<\/em>(ex. SIP)<\/li>\n<\/ul>\n<p id=\"16d4\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Vous devrez d\u00e9terminez lesquelles de ces fonctionnalit\u00e9s vous seront r\u00e9solument n\u00e9cessaires, ou non, avant d\u2019\u00eatre \u00e0 m\u00eame de d\u00e9terminer la bonne solution ou le bon outil pour votre application.<\/p>\n<h2 id=\"cda7\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">Solutions et outils<\/h2>\n<p id=\"1051\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Que ce soit pour le choix du protocole d\u2019initialisation en tant que tel, la mise en place des serveur ICE (STUN\/TURN), le choix d\u2019architecture ou les diff\u00e9rentes fonctionnalit\u00e9s que vous entendez offrir, diff\u00e9rentes solutions existent et faciliteront grandement le d\u00e9veloppement de votre application.<\/p>\n<h2 id=\"67c1\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Solution purement pair-\u00e0-pair<\/h2>\n<p id=\"e9db\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Pour une architecture enti\u00e8rement P2P (<em class=\"ky\">peer-to-peer<\/em>), donc bas\u00e9e sur le mod\u00e8le Mesh, vous aurez besoin de d\u00e9finir un protocole d\u2019initialisation et de mettre en place les serveurs de contournement (STUN\/TURN). Cette infrastructure h\u00e9berg\u00e9e sur place ou non sera tout de m\u00eame minimale et les efforts devront \u00eatre mis essentiellement dans le d\u00e9veloppement\u00a0<em class=\"ky\">frontend<\/em>\u00a0de l\u2019application.<\/p>\n<p id=\"b8d4\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">M\u00eame dans ce contexte, il sera conseill\u00e9 d\u2019utiliser une librairie\u00a0<em class=\"ky\">open source<\/em>\u00a0\u00e9tant donn\u00e9 la volatilit\u00e9 actuelle et la complexit\u00e9 relative du standard. \u00c0 ce chapitre, les diff\u00e9rentes librairies disponibles vont simplifier l\u2019utilisation des API MediaStream et RTCPeerConnection tout en offrant une m\u00e9thode d\u2019initialisation cl\u00e9-en-main et assurant la compatibilit\u00e9 multi-navigateur dans l\u2019\u00e9volution de la sp\u00e9cification.<\/p>\n<p id=\"3577\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Parmi les plus int\u00e9ressantes \u00e0 l\u2019heure actuelle, on notera:<\/p>\n<ul class=\"\">\n<li id=\"ad6d\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">simple-peer:\u00a0<a class=\"au lk\" href=\"https:\/\/github.com\/feross\/simple-peer\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/github.com\/feross\/simple-peer<\/a><\/li>\n<li id=\"2d44\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">SimpleWebRTC:\u00a0<a class=\"au lk\" href=\"https:\/\/github.com\/andyet\/SimpleWebRTC\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/github.com\/andyet\/SimpleWebRTC<\/a><\/li>\n<li id=\"3844\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">adapter.js:\u00a0<a class=\"au lk\" href=\"https:\/\/github.com\/webrtc\/adapter\" target=\"_blank\" rel=\"noopener ugc nofollow\">https:\/\/github.com\/webrtc\/adapter<\/a><\/li>\n<\/ul>\n<h2 id=\"30b5\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Serveur m\u00e9dia sur place (et\u00a0<em class=\"om\">open source<\/em>)<\/h2>\n<p id=\"1cd6\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Pour mettre en place une architecture MCU\/SFU et disposer de multiples fonctionnalit\u00e9s avanc\u00e9es propres aux applications de vid\u00e9oconf\u00e9rences pluripartites, en plus de disposer du plein contr\u00f4le sur votre infrastructure, vous aurez d\u00e9finitivement besoin d\u2019un serveur m\u00e9dia.<\/p>\n<p id=\"e06f\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Quelques outils semblent particuli\u00e8rement se distinguer.<\/p>\n<p id=\"db6c\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/jitsi.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"kc je\">Jitsi<\/strong><\/a>:<\/p>\n<ul class=\"\">\n<li id=\"afd8\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Projet mature, support\u00e9 par Atlassian et b\u00e9n\u00e9ficiant d\u2019une \u00e9norme communaut\u00e9 tr\u00e8s active<\/li>\n<li id=\"d2ea\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">License: Apache 2.0<\/li>\n<li id=\"c1c1\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Mod\u00e8le SFU avec un\u00a0<em class=\"ky\">signaling\u00a0<\/em>XMPP<\/li>\n<li id=\"4f04\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Offre beaucoup de fonctionnalit\u00e9s dont la messagerie, le partage d\u2019\u00e9cran (par l\u2019interm\u00e9diaire d\u2019un plugin), le transfert de fichiers, la suppression de bruits dans le flux audio, le cryptage des appels, etc.<\/li>\n<li id=\"4fe2\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Jitsi propose aussi une application Web (React) et mobile (React Native) moderne et compl\u00e8te<\/li>\n<li id=\"de56\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Connexion de participants SIP par Jigasi<\/li>\n<\/ul>\n<p id=\"1745\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/www.kurento.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"kc je\">Kurento<\/strong><\/a>:<\/p>\n<ul class=\"\">\n<li id=\"baa9\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Projet\u00a0<em class=\"ky\">open source<\/em>\u00a0plus ou moins abandonn\u00e9 en 2017 (apr\u00e8s son acquisition par Twilio), mais le projet a repris un nouveau souffle en 2018 avec la constitution d\u2019une nouvelle \u00e9quipe de d\u00e9veloppement<\/li>\n<li id=\"df85\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">License: Apache 2.0<\/li>\n<li id=\"c5c2\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Mod\u00e8le hybride SFU\/MCU<\/li>\n<li id=\"b85d\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Offre l\u2019enregistrement, le transcodage, l\u2019adaption du contenu vid\u00e9o, etc.<\/li>\n<li id=\"cc9a\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Offre des librairies\/SDK client pour faciliter les interactions avec le serveur (clients Java et JavaScript)<\/li>\n<li id=\"2781\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Supporte de multiples protocoles d\u2019initialisation<\/li>\n<\/ul>\n<p id=\"e136\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/mediasoup.org\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"kc je\">Mediasoup<\/strong><\/a><strong class=\"kc je\">:<\/strong><\/p>\n<ul class=\"\">\n<li id=\"ce6f\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Projet relativement nouveau bas\u00e9 autour d\u2019une petite communaut\u00e9<\/li>\n<li id=\"12f7\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">License: ISC<\/li>\n<li id=\"d562\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Nouvelle approche purement SFU d\u00e9velopp\u00e9e avec Node.js\/ES6<\/li>\n<li id=\"32d4\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Se charge de la couche multim\u00e9dia seulement, donc n\u2019inclut pas de protocole d\u2019initialisation<\/li>\n<li id=\"248c\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Offre du multi-flux audio\/video<\/li>\n<li id=\"41d8\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Offre une librairie JavaScript client<\/li>\n<li id=\"0bca\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Pas d\u2019enregistrement des flux et g\u00e9n\u00e9ralement peu de fonctionnalit\u00e9s par rapport aux autres.<\/li>\n<\/ul>\n<blockquote class=\"mo mp mq\">\n<p id=\"1c67\" class=\"ka kb ky kc b kd ke kf kg kh ki kj kk mr km kn ko ms kq kr ks mt ku kv kw kx iw gi\" data-selectable-paragraph=\"\"><strong class=\"kc je\">Note<\/strong>. Les license de\u00a0<a class=\"au lk\" href=\"https:\/\/janus.conf.meetecho.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Janus<\/a>\u00a0(\u00a0<a class=\"au lk\" href=\"http:\/\/www.gnu.org\/licenses\/gpl-3.0.en.html\" target=\"_blank\" rel=\"noopener ugc nofollow\">GPLv3<\/a>) et\u00a0<a class=\"au lk\" href=\"https:\/\/github.com\/medooze\/media-server\" target=\"_blank\" rel=\"noopener ugc nofollow\">Medooze<\/a>\u00a0(<a class=\"au lk\" href=\"https:\/\/www.gnu.org\/licenses\/old-licenses\/gpl-2.0.fr.html\" target=\"_blank\" rel=\"noopener ugc nofollow\">GPLv2<\/a>) excluaient ces produits de facto dans notre contexte, donc nous n\u2019avons pas approfondi particuli\u00e8rement ces produits.<\/p>\n<\/blockquote>\n<h2 id=\"4f8a\" class=\"na lm jd bn ln nb nc nd lr ne nf ng lv kl nh ni lz kp nj nk md kt nl nm mh nn gi\" data-selectable-paragraph=\"\">Plateforme de communication en tant que service<\/h2>\n<p id=\"eec6\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Diff\u00e9rents produits payants et offerts en tant que Communication-Platform-as-a-Service (CPaaS) existent aussi et vous offriront une infrastructure compl\u00e8te, stable et \u00e9volutive pour le d\u00e9veloppement de votre application de vid\u00e9oconf\u00e9rence bas\u00e9e sur WebRTC. Ces solutions offriront aussi une panoplie de fonctionnalit\u00e9s tr\u00e8s avanc\u00e9es \u00e0 la fine pointe de l\u2019industrie.<\/p>\n<p id=\"3383\" class=\"pw-post-body-paragraph ka kb jd kc b kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx iw gi\" data-selectable-paragraph=\"\">Parmi les plus matures et utilis\u00e9es, on conseillera:<\/p>\n<ul class=\"\">\n<li id=\"2d4d\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/www.twilio.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Twillio<\/a><\/li>\n<li id=\"31f8\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/www.vidyo.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Vidyo<\/a><\/li>\n<li id=\"7549\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\"><a class=\"au lk\" href=\"https:\/\/tokbox.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Tokbox<\/a><\/li>\n<\/ul>\n<h2 id=\"d424\" class=\"ll lm jd bn ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md me mf mg mh mi gi\">Conclusion<\/h2>\n<p id=\"8534\" class=\"pw-post-body-paragraph ka kb jd kc b kd mj kf kg kh mk kj kk kl ml kn ko kp mm kr ks kt mn kv kw kx iw gi\" data-selectable-paragraph=\"\">Notre expertise dans ce domaine \u00e9mergent est certainement limit\u00e9e, mais il est clair, \u00e0 la lecture des informations disponibles, que ces quelques petits conseils vont grandement faciliter la mise en place d\u2019une application WebRTC de vid\u00e9oconf\u00e9rence:<\/p>\n<ul class=\"\">\n<li id=\"6ff0\" class=\"np nq jd kc b kd ke kh ki kl nr kp ns kt nt kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Munissez votre \u00e9quipe de d\u00e9veloppement d\u2019une expertise r\u00e9seau<\/li>\n<li id=\"97c4\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">D\u00e9finissez vos cas d\u2019utilisation et vos fonctionnalit\u00e9s<\/li>\n<li id=\"0c0e\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Consid\u00e9rez longuement les diff\u00e9rents mod\u00e8les d\u2019architecture en fonction de vos besoins<\/li>\n<li id=\"ffea\" class=\"np nq jd kc b kd ny kh nz kl oa kp ob kt oc kx nu nv nw nx gi\" data-selectable-paragraph=\"\">Utilisez les outils disponibles<\/li>\n<\/ul>\n<p>Et n\u2019oubliez pas de savourer les joies de la vie!<\/p>\n<figure class=\"la lb lc ld hf le gt gu paragraph-image\">\n<div class=\"mv mw dq mx cf my\" tabindex=\"0\" role=\"button\">\n<div class=\"gt gu on\"><img loading=\"lazy\" decoding=\"async\" class=\"cf lf lg\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/max\/1400\/1*WxNMB2ZQfJSytVkhM3Js9w.jpeg\" alt=\"\" width=\"700\" height=\"467\" \/><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<div class=\"o dz oo op ii oq\" role=\"separator\"><\/div>\n<div class=\"iw ix iy iz ja\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Ce billet repr\u00e9sente le fruit d\u2019une veille technologique pr\u00e9alable \u00e0 la construction d\u2019une application Web de vid\u00e9oconf\u00e9rence bas\u00e9e sur une architecture moderne et utilisant les technologies disponibles en ce printemps 2018. Nous entendons par \u00abapplications Web\u00bb une application ne n\u00e9cessitant aucune installation suppl\u00e9mentaire et respectant les derniers standards Web recommand\u00e9s par le W3C. Cela exclut [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":16718,"menu_order":0,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":"","_links_to":"","_links_to_target":""},"mots_cles":[355,356,358,357],"categorie_blogue":[343],"class_list":["post-16723","blogue","type-blogue","status-publish","format-standard","has-post-thumbnail","hentry","mots_cles-application-web","mots_cles-protocoles","mots_cles-videoconference","mots_cles-webrtc","categorie_blogue-architecture-logicielle"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/blogue\/16723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/blogue"}],"about":[{"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/types\/blogue"}],"author":[{"embeddable":true,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/users\/18"}],"version-history":[{"count":6,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/blogue\/16723\/revisions"}],"predecessor-version":[{"id":22427,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/blogue\/16723\/revisions\/22427"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/media\/16718"}],"wp:attachment":[{"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/media?parent=16723"}],"wp:term":[{"taxonomy":"mots_cles","embeddable":true,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/mots_cles?post=16723"},{"taxonomy":"categorie_blogue","embeddable":true,"href":"https:\/\/www.crim.ca\/fr\/wp-json\/wp\/v2\/categorie_blogue?post=16723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}