W3docs

WebRTC

WebRTC (Web Real-Time Communication) est un projet open source et un ensemble de technologies web permettant la communication en temps réel entre navigateurs.

WebRTC : la communication en temps réel dans le navigateur

WebRTC (Web Real-Time Communication) est un standard ouvert et un ensemble d'API de navigateur qui permettent à deux navigateurs d'échanger de l'audio, de la vidéo et des données arbitraires directement entre eux — en pair-à-pair — sans faire transiter les médias par un serveur et sans aucun plugin. Il est au cœur des conférences vidéo, des appels vocaux, du partage d'écran, des états de jeu en direct et des transferts de fichiers à faible latence.

Ce chapitre explique ce que WebRTC vous apporte, les trois API sur lesquelles il repose, les concepts de signalisation et de traversée NAT qui déstabilisent la plupart des débutants, ainsi qu'un exemple complet de canal de données fonctionnel que vous pouvez exécuter sur cette page.

Ce que fait réellement WebRTC

Le navigateur sait déjà communiquer avec un serveur (voir API Fetch et WebSockets). WebRTC ajoute la pièce manquante : un moyen pour deux clients de se parler entre eux. Une fois une connexion pair ouverte, les médias et les données empruntent le chemin le plus court possible — souvent directement entre les deux machines — ce qui explique pourquoi la latence de WebRTC est bien inférieure à celle d'un relais par votre backend.

Cas d'utilisation typiques :

  • Appels audio et vidéo — voix/vidéo en temps réel, comme Zoom ou Google Meet.
  • Partage d'écran — capturer un écran ou une fenêtre avec getDisplayMedia() et le diffuser vers un pair.
  • Données en temps réel — état du jeu, chat, positions du curseur ou morceaux de fichiers via un RTCDataChannel.

Pourquoi utiliser WebRTC

  • Pair-à-pair, faible latence. Les médias circulent directement entre les pairs, pas via votre serveur, donc les allers-retours sont courts et votre facture de bande passante reste faible.
  • Sans plugin. Intégré à tous les navigateurs modernes — ni Flash, ni application native, ni téléchargement.
  • Chiffré par défaut. Les médias utilisent SRTP et les canaux de données utilisent DTLS ; le chiffrement est obligatoire et ne peut pas être désactivé.
  • Multi-plateforme. Fonctionne sur les navigateurs de bureau et mobiles ainsi que depuis des applications natives via le même standard.
  • Standard ouvert. Maintenu par le W3C et l'IETF, il continue de s'améliorer sans dépendance à un fournisseur.

Les trois API principales

WebRTC est en réalité trois API qui fonctionnent ensemble :

  1. API MediaStream (getUserMedia) — récupère l'audio/vidéo du microphone, de la caméra ou de l'écran sous forme de MediaStream.
  2. RTCPeerConnection — le cœur de WebRTC. Elle négocie, chiffre et maintient la connexion entre deux pairs et transporte les pistes média.
  3. RTCDataChannel — un canal bidirectionnel pour envoyer des données arbitraires (chaînes ou binaires) en pair-à-pair, similaire aux WebSockets mais sans serveur intermédiaire.

La signalisation : la partie que WebRTC ne fait pas

Deux navigateurs ne peuvent pas se trouver d'eux-mêmes. Avant qu'une connexion pair puisse s'ouvrir, les pairs doivent échanger deux types d'informations :

  • SDP (Session Description Protocol) — une « offre » et une « réponse » décrivant les codecs, les formats médias et les paramètres de connexion.
  • Candidats ICE — des adresses réseau possibles (paires IP/port) auxquelles chaque pair peut être joint.

WebRTC ne définit pas comment se déroule cet échange — c'est votre responsabilité, et cela s'appelle la signalisation. Vous construisez un canal de signalisation avec le transport serveur de votre choix ; WebSockets est le choix le plus courant. Le flux est toujours :

  1. L'appelant crée une offre et la transmet via le serveur de signalisation.
  2. L'appelé reçoit l'offre, crée une réponse et la renvoie.
  3. Les deux pairs échangent des candidats ICE au fur et à mesure de leur découverte.
  4. La connexion directe pair-à-pair est établie ; le serveur de signalisation n'est plus nécessaire.

STUN et TURN : passer les pare-feu

La plupart des appareils se trouvent derrière un NAT (Network Address Translation) et des pare-feu, de sorte qu'un pair connaît rarement sa propre adresse publique. Deux types de serveurs résolvent ce problème :

  • Serveur STUN — indique à un pair son IP/port public afin que les pairs puissent tenter une connexion directe. Bon marché et sans état ; Google en propose de publics et gratuits.
  • Serveur TURN — relaie les médias lorsqu'une connexion directe est impossible (pare-feu d'entreprise stricts). Il consomme de la bande passante, donc c'est un recours, pas le comportement par défaut.

Vous listez ces serveurs dans la configuration iceServers passée à RTCPeerConnection :

const configuration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    // A TURN server is added for hard-to-reach networks:
    // { urls: 'turn:turn.example.com', username: 'user', credential: 'pass' }
  ],
};

const peerConnection = new RTCPeerConnection(configuration);

Exemple : capturer la caméra avec getUserMedia

La première étape de tout appel vidéo consiste à obtenir le flux local. getUserMedia retourne une Promise, vous pouvez donc utiliser async/await :

<video id="localVideo" autoplay playsinline muted></video>
const localVideo = document.getElementById('localVideo');

async function startCamera() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true,
    });
    localVideo.srcObject = stream; // show the live camera feed
    return stream;
  } catch (error) {
    console.error('Could not access camera/microphone:', error.message);
  }
}

startCamera();

getUserMedia ne fonctionne que dans un contexte sécurisé (HTTPS ou localhost) et demande l'autorisation de l'utilisateur — vous ne pouvez jamais enregistrer quelqu'un en silence.

Exemple : un canal de données complet entre deux pairs

La façon la plus claire de voir WebRTC fonctionner est de connecter deux objets RTCPeerConnection entre eux dans un seul script. Ici, les deux pairs vivent dans la même page, donc nous pouvons câbler leur signalisation directement plutôt que via un serveur — l'échange SDP/ICE est exactement ce qu'un vrai serveur de signalisation transporterait. Collez ceci dans une console de navigateur sur n'importe quelle page HTTPS pour l'observer s'exécuter :

// Two peers, normally on different machines.
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();

// --- Signaling: hand each peer's ICE candidates to the other.
// In production this travels over WebSockets; here we call directly.
caller.onicecandidate = (e) => e.candidate && callee.addIceCandidate(e.candidate);
callee.onicecandidate = (e) => e.candidate && caller.addIceCandidate(e.candidate);

// The callee listens for the channel the caller opens.
callee.ondatachannel = (event) => {
  const channel = event.channel;
  channel.onmessage = (e) => {
    console.log('Callee received:', e.data);
    channel.send('pong'); // reply over the same channel
  };
};

// The caller creates the data channel.
const channel = caller.createDataChannel('chat');
channel.onopen = () => channel.send('ping');
channel.onmessage = (e) => console.log('Caller received:', e.data);

// --- Offer / answer negotiation.
async function connect() {
  const offer = await caller.createOffer();
  await caller.setLocalDescription(offer);
  await callee.setRemoteDescription(offer);

  const answer = await callee.createAnswer();
  await callee.setLocalDescription(answer);
  await caller.setRemoteDescription(answer);
}

connect();
// Logs:
// Callee received: ping
// Caller received: pong

Le schéma est identique pour la vidéo : au lieu de createDataChannel, vous appelez peerConnection.addTrack(track, stream) pour chaque piste issue de getUserMedia, et vous lisez les médias entrants dans un gestionnaire ontrack :

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach((track) => peerConnection.addTrack(track, stream));

// The remote peer's media arrives here:
peerConnection.ontrack = (event) => {
  document.getElementById('remoteVideo').srcObject = event.streams[0];
};

Pièges courants

  • HTTPS est obligatoire. getUserMedia et getDisplayMedia échouent en dehors d'un contexte sécurisé (HTTPS ou localhost).
  • Vous avez toujours besoin d'un serveur de signalisation. WebRTC gère les médias, mais vous devez construire l'échange offre/réponse/ICE vous-même — généralement via WebSockets.
  • Créez toujours l'offre/réponse dans l'ordre. setLocalDescription doit s'exécuter avant setRemoteDescription pour le côté correspondant, sinon la négociation échoue.
  • N'oubliez pas un serveur TURN en production. STUN seul échoue sur les réseaux restrictifs ; sans TURN, environ 10 à 20 % des connexions réelles ne s'établiront pas.
  • Les permissions peuvent être refusées. Enveloppez getUserMedia dans un try/catch et gérez le rejet de manière gracieuse.

Résumé

WebRTC donne au navigateur un véritable audio, vidéo et échange de données en pair-à-pair. Utilisez getUserMedia pour capturer les médias, RTCPeerConnection pour négocier et maintenir la connexion, et RTCDataChannel pour les données arbitraires. WebRTC ne fournit pas la signalisation — vous échangez vous-même les offres/réponses SDP et les candidats ICE, généralement via WebSockets, et configurez des serveurs STUN/TURN pour traverser le NAT. Avec ces éléments en place, vous pouvez créer des appels vidéo, du partage d'écran et de la collaboration en temps réel entièrement dans le navigateur.

Pratique

Pratique
Lesquelles des affirmations suivantes sont de vraies capacités de WebRTC ?
Lesquelles des affirmations suivantes sont de vraies capacités de WebRTC ?
Was this page helpful?