Premiers pas avec WebRTC

WebRTC est un nouveau front dans la longue guerre pour un Web ouvert et sans entrave.

Brendan Eich, inventeur de JavaScript

Communication en temps réel sans plug-ins

Imaginez un monde où votre téléphone, votre téléviseur et votre ordinateur pourraient communiquer sur une plate-forme commune. Imaginez qu'il soit facile d'ajouter le chat vidéo et le partage de données peer-to-peer à votre application Web. C'est la vision de WebRTC.

Ça vous tente ? WebRTC est disponible sur ordinateur et mobile dans Google Chrome, Safari, Firefox et Opera. Vous pouvez commencer par utiliser l'application de chat vidéo simple appr.tc :

  1. Ouvrez appr.tc dans votre navigateur.
  2. Cliquez sur Rejoindre pour rejoindre un salon de discussion et autoriser l'application à utiliser votre webcam.
  3. Ouvrez l'URL affichée à la fin de la page dans un nouvel onglet ou, mieux encore, sur un autre ordinateur.

Démarrage rapide

Vous n'avez pas le temps de lire cet article ou vous ne voulez que du code ?

  • Pour obtenir une présentation de WebRTC, regardez la vidéo Google I/O suivante ou consultez ces diapositives :
  • Si vous n'avez pas utilisé l'API getUserMedia, consultez Capture audio and video in HTML5 (Capturer l'audio et la vidéo en HTML5) et simpl.info getUserMedia.
  • Pour en savoir plus sur l'API RTCPeerConnection, consultez l'exemple suivant et simpl.info RTCPeerConnection.
  • Pour découvrir comment WebRTC utilise les serveurs pour la signalisation, ainsi que le balayage de pare-feu et de NAT, consultez le code et les journaux de la console sur appr.tc.
  • Vous n'avez pas la patience d'attendre et vous voulez essayer WebRTC tout de suite ? Essayez l'une des plus de 20 démos qui utilisent les API JavaScript WebRTC.
  • Vous rencontrez des problèmes avec votre ordinateur et WebRTC ? Accédez à l'outil de dépannage WebRTC.

Vous pouvez également passer directement à l'atelier de programmation WebRTC, un guide pas à pas qui explique comment créer une application de chat vidéo complète, y compris un serveur de signalisation simple.

Bref historique de WebRTC

L'un des derniers défis majeurs pour le Web est de permettre la communication humaine par la voix et la vidéo : la communication en temps réel ou RTC (Real-Time Communication). La communication en temps réel doit être aussi naturelle dans une application Web que la saisie de texte dans un champ de saisie de texte. Sans cela, votre capacité à innover et à développer de nouvelles façons d'interagir est limitée.

Historiquement, la RTC était une technologie complexe et réservée aux entreprises, qui nécessitait de concéder des licences ou de développer en interne des technologies audio et vidéo coûteuses. L'intégration de la technologie RTC aux contenus, données et services existants s'est avérée difficile et chronophage, en particulier sur le Web.

Le chat vidéo Gmail est devenu populaire en 2008. En 2011, Google a lancé Hangouts, qui utilise Talk (comme Gmail). Google a acheté GIPS, une entreprise qui a développé de nombreux composants nécessaires à la RTC, tels que des codecs et des techniques d'annulation d'écho. Google a rendu open source les technologies développées par GIPS et s'est engagé auprès des organismes de normalisation concernés de l'Internet Engineering Task Force (IETF) et du World Wide Web Consortium (W3C) pour assurer un consensus dans le secteur. En mai 2011, Ericsson a créé la première implémentation de WebRTC.

WebRTC a implémenté des normes ouvertes pour la communication vidéo, audio et de données en temps réel et sans plug-in. Le besoin était réel :

  • De nombreux services Web utilisaient RTC, mais nécessitaient des téléchargements, des applications natives ou des plug-ins. Skype, Facebook et Hangouts, par exemple.
  • Le téléchargement, l'installation et la mise à jour des plug-ins sont complexes, sources d'erreurs et fastidieux.
  • Les plug-ins sont difficiles à déployer, à déboguer, à dépanner, à tester et à entretenir. Ils peuvent également nécessiter une licence et une intégration à une technologie complexe et coûteuse. Il est souvent difficile de persuader les utilisateurs d'installer des plug-ins.

Les principes fondamentaux du projet WebRTC sont que ses API doivent être Open Source, sans frais, standardisées, intégrées aux navigateurs Web et plus efficaces que les technologies existantes.

Où en sommes-nous maintenant ?

WebRTC est utilisé dans diverses applications, comme Google Meet. WebRTC a également été intégré aux applications natives WebKitGTK+ et Qt.

WebRTC implémente les trois API suivantes : - MediaStream (également appelée getUserMedia) - RTCPeerConnectionRTCDataChannel

Les API sont définies dans les deux spécifications suivantes :

Les trois API sont compatibles avec Chrome, Safari, Firefox, Edge et Opera sur mobile et ordinateur.

getUserMedia : pour les démos et le code, consultez les exemples WebRTC ou essayez les exemples étonnants de Chris Wilson qui utilisent getUserMedia comme entrée pour le Web Audio.

RTCPeerConnection : Pour une démo simple et une application de chat vidéo entièrement fonctionnelle, consultez respectivement Exemples WebRTC : connexion peer-to-peer et appr.tc. Cette application utilise adapter.js, un shim JavaScript géré par Google avec l'aide de la communauté WebRTC, pour faire abstraction des différences entre les navigateurs et des modifications apportées aux spécifications.

RTCDataChannel : Pour voir cela en action, consultez les exemples WebRTC et découvrez l'une des démos sur les canaux de données.

L'atelier de programmation WebRTC montre comment utiliser les trois API pour créer une application simple de chat vidéo et de partage de fichiers.

Votre première application WebRTC

Les applications WebRTC doivent effectuer plusieurs actions :

  • Obtenez des données audio, vidéo ou autres en streaming.
  • Obtenir des informations sur le réseau, telles que les adresses IP et les ports, et les échanger avec d'autres clients WebRTC (appelés pairs) pour permettre la connexion, même via des NAT et des pare-feu.
  • Coordonne la communication de signalisation pour signaler les erreurs et lancer ou fermer les sessions.
  • Échangez des informations sur les capacités du client et du contenu multimédia, comme la résolution et les codecs.
  • Communiquer des données, ou des contenus audio ou vidéo en streaming.

Pour acquérir et communiquer des données de streaming, WebRTC implémente les API suivantes :

  • MediaStream accède aux flux de données, par exemple à ceux de la caméra et du micro de l'utilisateur.
  • RTCPeerConnection permet de passer des appels audio ou vidéo avec des fonctionnalités de chiffrement et de gestion de la bande passante.
  • RTCDataChannel permet la communication peer-to-peer de données génériques.

(Nous aborderons plus en détail les aspects réseau et de signalisation de WebRTC plus tard.)

API MediaStream (également appelée API getUserMedia)

L'API MediaStream représente des flux multimédias synchronisés. Par exemple, un flux provenant d'une entrée de caméra et de micro comporte des pistes vidéo et audio synchronisées. (Ne confondez pas MediaStreamTrack avec l'élément <track>, qui est complètement différent.)

Le moyen le plus simple de comprendre l'API MediaStream est probablement de l'observer en action :

  1. Dans votre navigateur, accédez à Exemples WebRTC getUserMedia.
  2. Ouvrez la console.
  3. Inspectez la variable stream, qui se trouve dans le champ d'application global.

Chaque MediaStream possède une entrée, qui peut être un MediaStream généré par getUserMedia(), et une sortie, qui peut être transmise à un élément vidéo ou à un RTCPeerConnection.

La méthode getUserMedia() utilise un paramètre d'objet MediaStreamConstraints et renvoie un Promise qui se résout en un objet MediaStream.

Chaque MediaStream possède un label, tel que 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'. Un tableau de MediaStreamTrack est renvoyé par les méthodes getAudioTracks() et getVideoTracks().

Pour l'exemple getUserMedia, stream.getAudioTracks() renvoie un tableau vide (car il n'y a pas d'audio) et, en supposant qu'une webcam fonctionnelle soit connectée, stream.getVideoTracks() renvoie un tableau d'un MediaStreamTrack représentant le flux de la webcam. Chaque MediaStreamTrack possède un type ('video' ou 'audio'), un label (par exemple, 'FaceTime HD Camera (Built-in)') et représente un ou plusieurs canaux audio ou vidéo. Dans ce cas, il n'y a qu'une seule piste vidéo et aucune piste audio, mais il est facile d'imaginer des cas d'utilisation où il y en a plusieurs, comme une application de chat qui reçoit des flux de la caméra avant, de la caméra arrière, du micro et une application qui partage son écran.

Un MediaStream peut être associé à un élément vidéo en définissant l'attribut srcObject. Auparavant, cela se faisait en définissant l'attribut src sur une URL d'objet créée avec URL.createObjectURL(), mais cette méthode est obsolète.

getUserMedia peut également être utilisé comme nœud d'entrée pour l'API Web Audio :

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

Les applications et extensions basées sur Chromium peuvent également intégrer getUserMedia. L'ajout des autorisations audioCapture et/ou videoCapture au fichier manifeste permet de demander et d'accorder l'autorisation une seule fois lors de l'installation. Par la suite, l'utilisateur n'est plus invité à autoriser l'accès à la caméra ou au micro.

Vous n'avez besoin d'accorder l'autorisation qu'une seule fois pour getUserMedia(). La première fois, un bouton "Autoriser" s'affiche dans la barre d'informations du navigateur. L'accès HTTP pour getUserMedia() a été abandonné par Chrome à la fin de l'année 2015, car il était classé comme fonctionnalité puissante.

L'intention est potentiellement d'activer un MediaStream pour n'importe quelle source de données de streaming, et pas seulement une caméra ou un micro. Cela permettrait de diffuser des données stockées ou des sources de données arbitraires, telles que des capteurs ou d'autres entrées.

getUserMedia() prend tout son sens lorsqu'il est combiné à d'autres API et bibliothèques JavaScript :

  • Webcam Toy est une application de photobooth qui utilise WebGL pour ajouter des effets étranges et merveilleux aux photos, qui peuvent être partagées ou enregistrées localement.
  • FaceKat est un jeu de suivi du visage créé avec headtrackr.js.
  • ASCII Camera utilise l'API Canvas pour générer des images ASCII.
Image ASCII générée par idevelop.ro/ascii-camera
gUM ASCII art!

Contraintes

Les contraintes peuvent être utilisées pour définir des valeurs de résolution vidéo pour getUserMedia(). Cela permet également la prise en charge d'autres contraintes, telles que le format, le mode de caméra (avant ou arrière), la fréquence d'images, la hauteur et la largeur, ainsi qu'une méthode applyConstraints().

Pour obtenir un exemple, consultez Exemples WebRTC getUserMedia : sélectionner la résolution.

Si vous définissez une valeur de contrainte non autorisée, vous obtiendrez un DOMException ou un OverconstrainedError (par exemple, si une résolution demandée n'est pas disponible). Pour voir cela en action, consultez Exemples WebRTC getUserMedia : sélectionner la résolution pour une démonstration.

Capture d'écran et d'onglet

Les applications Chrome permettent également de partager une vidéo en direct d'un seul onglet de navigateur ou de l'intégralité du bureau grâce aux API chrome.tabCapture et chrome.desktopCapture. (Pour une démonstration et plus d'informations, consultez Partage d'écran avec WebRTC.) L'article date de quelques années, mais il reste intéressant.)

Il est également possible d'utiliser la capture d'écran comme source MediaStream dans Chrome à l'aide de la contrainte expérimentale chromeMediaSource. Notez que la capture d'écran nécessite le protocole HTTPS et ne doit être utilisée que pour le développement, car elle est activée par le biais d'un indicateur de ligne de commande, comme expliqué dans cet article.

Signalisation : contrôle de session, informations sur le réseau et les contenus multimédias

WebRTC utilise RTCPeerConnection pour communiquer des données de streaming entre les navigateurs (également appelés pairs), mais a également besoin d'un mécanisme pour coordonner la communication et envoyer des messages de contrôle, un processus appelé signalisation. Les méthodes et protocoles de signalisation ne sont pas spécifiés par WebRTC. La signalisation ne fait pas partie de l'API RTCPeerConnection.

Au lieu de cela, les développeurs d'applications WebRTC peuvent choisir le protocole de messagerie de leur choix, tel que SIP ou XMPP, et tout canal de communication duplex (bidirectionnel) approprié. L'exemple appr.tc utilise XHR et l'API Channel comme mécanisme de signalisation. L'codelab utilise Socket.io exécuté sur un serveur Node.

La signalisation permet d'échanger trois types d'informations :

  • Messages de contrôle de session : pour initialiser ou fermer la communication et signaler les erreurs.
  • Configuration réseau : quelle est l'adresse IP et le port de votre ordinateur pour le monde extérieur ?
  • Capacités multimédias : quels codecs et résolutions votre navigateur et celui avec lequel il souhaite communiquer peuvent-ils gérer ?

L'échange d'informations via la signalisation doit avoir réussi avant que la diffusion en streaming peer-to-peer puisse commencer.

Par exemple, imaginons qu'Alice souhaite communiquer avec Bob. Voici un exemple de code tiré de la spécification WebRTC du W3C, qui montre le processus de signalisation en action. Le code suppose l'existence d'un mécanisme de signalisation créé dans la méthode createSignalingChannel(). Notez également que sur Chrome et Opera, RTCPeerConnection est actuellement préfixé.

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // Send the offer to the other peer.
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// Once remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

Tout d'abord, Alice et Bob échangent des informations sur le réseau. (L'expression recherche de candidats fait référence au processus de recherche d'interfaces et de ports réseau à l'aide du framework ICE.)

  1. Alice crée un objet RTCPeerConnection avec un gestionnaire onicecandidate, qui s'exécute lorsque des candidats réseau deviennent disponibles.
  2. Alice envoie les données candidates sérialisées à Bob via le canal de signalisation qu'ils utilisent, comme WebSocket ou un autre mécanisme.
  3. Lorsque Bob reçoit un message candidat d'Alice, il appelle addIceCandidate pour ajouter le candidat à la description du pair distant.

Les clients WebRTC (également appelés pairs, ou Alice et Bob dans cet exemple) doivent également identifier et échanger des informations sur les contenus multimédias audio et vidéo locaux et distants, telles que la résolution et les capacités de codec. La signalisation pour échanger des informations de configuration multimédia se fait en échangeant une offre et une réponse à l'aide du protocole de description de session (SDP, Session Description Protocol) :

  1. Alice exécute la méthode createOffer().RTCPeerConnection Le retour de cette opération est transmis à une RTCSessionDescription, qui correspond à la description de la session locale d'Alice.
  2. Dans le rappel, Alice définit la description locale à l'aide de setLocalDescription(), puis envoie cette description de session à Bob via son canal de signalisation. Notez que RTCPeerConnection ne commencera à collecter des candidats qu'une fois setLocalDescription() appelé. Cela est codifié dans le projet IETF JSEP.
  3. Bob définit la description qu'Alice lui a envoyée comme description distante à l'aide de setRemoteDescription().
  4. Bob exécute la méthode createAnswer() RTCPeerConnection, en lui transmettant la description à distance qu'il a reçue d'Alice afin de générer une session locale compatible avec la sienne. Le rappel createAnswer() reçoit un RTCSessionDescription. Bob définit cette description comme description locale et l'envoie à Alice.
  5. Lorsqu'Alice reçoit la description de session de Bob, elle la définit comme description distante avec setRemoteDescription.
  6. Ping !

Les objets RTCSessionDescription sont des blobs conformes au Session Description Protocol (SDP). Un objet SDP sérialisé se présente comme suit :

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

L'acquisition et l'échange d'informations sur le réseau et les contenus multimédias peuvent être effectués simultanément, mais les deux processus doivent être terminés avant que le streaming audio et vidéo entre pairs puisse commencer.

L'architecture offre/réponse décrite précédemment est appelée JavaScript Session Establishment Protocol, ou JSEP. (Une excellente animation expliquant le processus de signalisation et de streaming est disponible dans la vidéo de démonstration d'Ericsson pour sa première implémentation WebRTC.)

Schéma de l&#39;architecture JSEP
Architecture JSEP

Une fois le processus de signalisation terminé, les données peuvent être diffusées en streaming directement de pair à pair, entre l'appelant et l'appelé. Si cela échoue, elles peuvent être diffusées via un serveur relais intermédiaire (nous y reviendrons plus tard). Le streaming est la tâche de RTCPeerConnection.

RTCPeerConnection

RTCPeerConnection est le composant WebRTC qui gère la communication stable et efficace des données de streaming entre les pairs.

Voici un schéma de l'architecture WebRTC montrant le rôle de RTCPeerConnection. Comme vous le remarquerez, les parties vertes sont complexes.

Schéma de l&#39;architecture WebRTC
Architecture WebRTC (issue de webrtc.org)

Du point de vue de JavaScript, la principale chose à comprendre dans ce diagramme est que RTCPeerConnection protège les développeurs Web des innombrables complexités qui se cachent en dessous. Les codecs et protocoles utilisés par WebRTC font un travail considérable pour rendre la communication en temps réel possible, même sur des réseaux peu fiables :

  • Masquage de la perte de paquets
  • Annulation de l'écho
  • Adaptabilité de la bande passante
  • Mise en mémoire tampon dynamique de la gigue
  • Contrôle automatique du gain
  • Réduction et suppression du bruit
  • Nettoyage d'images

Le code W3C précédent montre un exemple simplifié de WebRTC du point de vue de la signalisation. Vous trouverez ci-dessous des présentations de deux applications WebRTC fonctionnelles. Le premier est un exemple simple pour illustrer RTCPeerConnection, et le second est un client de chat vidéo entièrement opérationnel.

RTCPeerConnection sans serveurs

Le code suivant est extrait de l'exemple de connexion peer-to-peer WebRTC, qui comporte des RTCPeerConnection locaux et distants (ainsi que des vidéos locales et distantes) sur une seule page Web. Cela ne constitue rien de très utile (l'appelant et l'appelé sont sur la même page), mais cela rend le fonctionnement de l'API RTCPeerConnection un peu plus clair, car les objets RTCPeerConnection de la page peuvent échanger des données et des messages directement sans avoir à utiliser de mécanismes de signalisation intermédiaires.

Dans cet exemple, pc1 représente le pair local (l'appelant) et pc2 représente le pair distant (le destinataire de l'appel).

Appelant

  1. Créez un RTCPeerConnection et ajoutez le flux à partir de getUserMedia() : ```js // Servers is an optional configuration file. (Voir la discussion sur TURN et STUN plus loin.) pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream); });
  1. Créez une offre et définissez-la comme description locale pour pc1 et comme description distante pour pc2. Cela peut être fait directement dans le code sans utiliser de signalisation, car l'appelant et l'appelé se trouvent sur la même page : js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

Callee

  1. Créez pc2 et, lorsque le flux de pc1 est ajouté, affichez-le dans un élément vidéo : js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

Serveurs et API RTCPeerConnection

Dans le monde réel, WebRTC a besoin de serveurs, même simples, pour que les éléments suivants puissent se produire :

  • Les utilisateurs se découvrent mutuellement et échangent des informations réelles, comme des noms.
  • Les applications clientes WebRTC (pairs) échangent des informations sur le réseau.
  • Les pairs échangent des données sur les contenus multimédias, comme le format et la résolution vidéo.
  • Les applications clientes WebRTC traversent les passerelles NAT et les pare-feu.

En d'autres termes, WebRTC a besoin de quatre types de fonctionnalités côté serveur :

  • Découverte et communication avec les utilisateurs
  • Serveur de signalement
  • Traversée de pare-feu/NAT
  • Serveurs relais en cas d'échec de la communication peer-to-peer

Le parcours NAT, la mise en réseau peer-to-peer et les exigences pour créer une application serveur pour la découverte et la signalisation des utilisateurs dépassent le cadre de cet article. Il suffit de dire que le protocole STUN et son extension TURN sont utilisés par le framework ICE pour permettre à RTCPeerConnection de faire face au balayage NAT et à d'autres aléas du réseau.

ICE est un framework permettant de connecter des pairs, tels que deux clients de chat vidéo. Au départ, ICE tente de connecter les pairs directement avec la latence la plus faible possible via UDP. Dans ce processus, les serveurs STUN n'ont qu'une seule tâche : permettre à un pair situé derrière un NAT de trouver son adresse et son port publics. (Pour en savoir plus sur STUN et TURN, consultez Créer les services de backend nécessaires pour une application WebRTC.)

Trouver des candidats à la connexion
Rechercher des candidats à l'ajout

Si UDP échoue, ICE tente TCP. Si la connexion directe échoue (en particulier en raison du balayage NAT et des pare-feu d'entreprise), ICE utilise un serveur TURN intermédiaire (relais). En d'autres termes, ICE utilise d'abord STUN avec UDP pour connecter directement les pairs et, en cas d'échec, revient à un serveur relais TURN. L'expression recherche de candidats fait référence au processus de recherche d'interfaces et de ports réseau.

Chemins de données WebRTC
Chemins de données WebRTC

Justin Uberti, ingénieur WebRTC, fournit plus d'informations sur ICE, STUN et TURN dans la présentation WebRTC de Google I/O 2013. (Les diapositives de la présentation donnent des exemples d'implémentations de serveurs TURN et STUN.)

Un client de chat vidéo simple

La démo de chat vidéo sur appr.tc est un bon point de départ pour essayer WebRTC, avec la signalisation et le balayage NAT/pare-feu à l'aide d'un serveur STUN. Cette application utilise adapter.js, un shim permettant d'isoler les applications des modifications de spécifications et des différences de préfixes.

Le code est délibérément verbeux dans sa journalisation. Consultez la console pour comprendre l'ordre des événements. Vous trouverez ci-dessous une présentation détaillée du code.

Topologies de réseaux

WebRTC, tel qu'il est actuellement implémenté, ne prend en charge que la communication en tête-à-tête, mais pourrait être utilisé dans des scénarios réseau plus complexes, par exemple avec plusieurs pairs communiquant chacun entre eux directement ou via une unité de contrôle multipoint (MCU, Multipoint Control Unit), un serveur capable de gérer un grand nombre de participants et d'effectuer le transfert sélectif de flux, ainsi que le mixage ou l'enregistrement de l'audio et de la vidéo.

Schéma de topologie de l&#39;unité de contrôle multipoint
Exemple de topologie d'unité de contrôle multipoint

De nombreuses applications WebRTC existantes ne montrent que la communication entre navigateurs Web, mais les serveurs de passerelle peuvent permettre à une application WebRTC exécutée sur un navigateur d'interagir avec des appareils, tels que des téléphones (également appelés PSTN) et des systèmes VOIP. En mai 2012, Doubango Telecom a rendu Open Source le client SIP sipml5 conçu avec WebRTC et WebSocket, qui (entre autres utilisations potentielles) permet les appels vidéo entre les navigateurs et les applications fonctionnant sous iOS et Android. Lors de Google I/O, Tethr et Tropo ont présenté un framework de communication en cas de catastrophe dans une mallette à l'aide d'une cellule OpenBTS pour permettre la communication entre les téléphones classiques et les ordinateurs via WebRTC. Communiquez par téléphone sans opérateur !

Démonstration de Tethr/Tropo à Google I/O 2012
Tethr/Tropo : communications en cas de catastrophe dans une mallette

API RTCDataChannel<

En plus de l'audio et de la vidéo, WebRTC permet la communication en temps réel pour d'autres types de données.

L'API RTCDataChannel permet l'échange de données arbitraires de pair à pair avec une faible latence et un débit élevé. Pour obtenir des démonstrations monopages et apprendre à créer une application de transfert de fichiers simple, consultez respectivement les exemples WebRTC et l'atelier de programmation WebRTC.

L'API peut être utilisée dans de nombreux cas, y compris :

  • Jeux vidéo
  • Applications de bureau à distance
  • Chat textuel en temps réel
  • Transfert de fichiers
  • Réseaux décentralisés

L'API comporte plusieurs fonctionnalités pour tirer le meilleur parti de RTCPeerConnection et permettre une communication peer-to-peer puissante et flexible :

  • Utilisation de la configuration de session RTCPeerConnection
  • Plusieurs canaux simultanés avec priorisation
  • Sémantique de diffusion fiable et non fiable
  • Sécurité (DTLS) et contrôle de l'encombrement intégrés
  • Possibilité d'utiliser l'application avec ou sans contenu audio ou vidéo

La syntaxe est délibérément semblable à celle de WebSocket, avec une méthode send() et un événement message :

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

La communication s'effectue directement entre les navigateurs. RTCDataChannel peut donc être beaucoup plus rapide que WebSocket, même si un serveur relais (TURN) est nécessaire lorsque le forçage de connexion pour faire face aux pare-feu et aux NAT échoue.

RTCDataChannel est disponible dans Chrome, Safari, Firefox, Opera et Samsung Internet. Le jeu Cube Slam utilise l'API pour communiquer l'état du jeu. Jouez avec un ami ou avec l'ours ! La plate-forme innovante Sharefest, qui permettait le partage de fichiers via RTCDataChannel, et peerCDN ont donné un aperçu de la façon dont WebRTC pouvait permettre la distribution de contenu peer-to-peer.

Pour en savoir plus sur RTCDataChannel, consultez la spécification provisoire du protocole de l'IETF.

Sécurité

Il existe plusieurs façons dont une application ou un plug-in de communication en temps réel peuvent compromettre la sécurité. Exemple :

  • Les données ou contenus multimédias non chiffrés peuvent être interceptés entre les navigateurs, ou entre un navigateur et un serveur.
  • Une application peut enregistrer et distribuer des vidéos ou des contenus audio à l'insu de l'utilisateur.
  • Des logiciels malveillants ou des virus peuvent être installés en même temps qu'un plug-in ou une application apparemment inoffensifs.

WebRTC dispose de plusieurs fonctionnalités pour éviter ces problèmes :

  • Les implémentations WebRTC utilisent des protocoles sécurisés, tels que DTLS et SRTP.
  • Le chiffrement est obligatoire pour tous les composants WebRTC, y compris les mécanismes de signalisation.
  • WebRTC n'est pas un plug-in. Ses composants s'exécutent dans le bac à sable du navigateur et non dans un processus distinct. Les composants ne nécessitent pas d'installation distincte et sont mis à jour à chaque mise à jour du navigateur.
  • L'accès à la caméra et au micro doit être accordé de manière explicite. Lorsque la caméra ou le micro sont en cours d'utilisation, l'interface utilisateur l'indique clairement.

L'examen complet de la sécurité des contenus multimédias en streaming dépasse le cadre de cet article. Pour en savoir plus, consultez l'architecture de sécurité WebRTC proposée par l'IETF.

En conclusion

Les API et les normes de WebRTC peuvent démocratiser et décentraliser les outils de création de contenu et de communication, y compris la téléphonie, les jeux, la production vidéo, la création musicale et la collecte d'informations.

Il est difficile de trouver une technologie plus disruptive.

Comme l'a expliqué le blogueur Phil Edholm, "WebRTC et HTML5 pourraient potentiellement permettre la même transformation pour la communication en temps réel que le navigateur d'origine pour l'information".

Outils pour les développeurs

  • Vous trouverez les statistiques WebRTC d'une session en cours à l'adresse suivante :
    • about://webrtc-internals dans Chrome
    • opera://webrtc-internals dans Opera
    • about:webrtc dans Firefox
      Page chrome://webrtc-internals
      Capture d'écran de chrome://webrtc-internals
  • Notes d'interopérabilité entre navigateurs
  • adapter.js est un shim JavaScript pour WebRTC géré par Google avec l'aide de la communauté WebRTC. Il permet d'abstraire les préfixes de fournisseur, les différences entre navigateurs et les modifications de spécifications.
  • Pour en savoir plus sur les processus de signalisation WebRTC, consultez la sortie du journal appr.tc dans la console.
  • Si tout cela vous semble trop compliqué, vous préférerez peut-être utiliser un framework WebRTC ou même un service WebRTC complet.
  • Nous apprécions toujours les rapports de bugs et les demandes de fonctionnalités :

En savoir plus

Normes et protocoles

Résumé de la compatibilité WebRTC

API MediaStream et getUserMedia

  • Chrome sur ordinateur 18.0.1008 ou version ultérieure ; Chrome pour Android 29 ou version ultérieure
  • Opera 18 ou version ultérieure ; Opera pour Android 20 ou version ultérieure
  • Opera 12, Opera Mobile 12 (basé sur le moteur Presto)
  • Firefox 17 ou version ultérieure
  • Microsoft Edge 16 ou version ultérieure
  • Safari 11.2 ou version ultérieure sur iOS, et 11.1 ou version ultérieure sur macOS
  • UC 11.8 ou version ultérieure sur Android
  • Samsung Internet 4 ou version ultérieure

API RTCPeerConnection

  • Chrome sur ordinateur 20 ou version ultérieure ; Chrome pour Android 29 ou version ultérieure (sans indicateur)
  • Opera 18 ou version ultérieure (activé par défaut) ; Opera pour Android 20 ou version ultérieure (activé par défaut)
  • Firefox 22 ou version ultérieure (activé par défaut)
  • Microsoft Edge 16 ou version ultérieure
  • Safari 11.2 ou version ultérieure sur iOS, et 11.1 ou version ultérieure sur macOS
  • Samsung Internet 4 ou version ultérieure

API RTCDataChannel

  • Version expérimentale dans Chrome 25, mais plus stable (et interopérable avec Firefox) dans Chrome 26 et versions ultérieures ; Chrome pour Android 29 et versions ultérieures
  • Version stable (et avec l'interopérabilité Firefox) dans Opera 18 et versions ultérieures ; Opera pour Android 20 et versions ultérieures
  • Firefox 22 ou version ultérieure (activé par défaut)

Pour en savoir plus sur la compatibilité multiplate-forme des API, telles que getUserMedia et RTCPeerConnection, consultez caniuse.com et État de la plate-forme Chrome.

Des API natives pour RTCPeerConnection sont également disponibles dans la documentation sur webrtc.org.