Start · Sprachen · JavaScript · Referenz · RTCIceCandidateStats

RTCIceCandidateStats

Schnittstelle

Wörterbuch der WebRTC-Statistik-API, das Angaben zu einem lokalen oder entfernten ICE-Kandidaten liefert, z. B. Adresse, Port, Protokoll und Kandidatentyp.

seit JavaScript Baseline: Chrome, Edge, Firefox, Safari (Felder te Kategorie: webapi

Signatur

interface RTCIceCandidateStats extends RTCStats

Beschreibung

RTCIceCandidateStats ist ein Wörterbuch (Dictionary) der WebRTC-API. Es beschreibt einen einzelnen ICE-Kandidaten, den die Verbindung gesammelt (lokal) oder von der Gegenseite erhalten hat (entfernt). Solche Objekte bekommt man nicht über einen Konstruktor, sondern als Einträge des RTCStatsReport, den RTCPeerConnection.getStats() zurückgibt. Ihr type ist entweder "local-candidate" oder "remote-candidate".

Wichtige Felder sind unter anderem:

  • address / port: IP-Adresse (oder mDNS-Hostname) und Port des Kandidaten.
  • protocol: "udp" oder "tcp".
  • candidateType: "host", "srflx" (über STUN ermittelt), "prflx" (peer-reflexiv) oder "relay" (TURN).
  • priority, foundation, transportId, url (STUN/TURN-Server-URL bei lokalen Kandidaten), relayProtocol (Protokoll zwischen Client und TURN-Server), tcpType, usernameFragment.
  • Geerbt von RTCStats: id, timestamp, type.

In der Praxis nutzt man diese Statistiken vor allem zur Fehlersuche und Überwachung: Man findet heraus, ob eine Verbindung direkt (host/srflx) oder über einen TURN-Relay läuft, was sich auf Latenz und Serverkosten auswirkt. Dazu verknüpft man das aktive RTCIceCandidatePairStats (Felder localCandidateId/remoteCandidateId) mit den passenden Kandidaten-Einträgen.

Rückgabewert

Typ
RTCIceCandidateStats
Beschreibung
Ein reines Datenobjekt innerhalb eines RTCStatsReport (einer Map-ähnlichen Struktur), mit type "local-candidate" oder "remote-candidate".

Beispiele

Alle lokalen und entfernten Kandidaten auflisten

const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
pc.createDataChannel('probe');
await pc.setLocalDescription(await pc.createOffer());

// Kurz warten, bis ICE-Kandidaten gesammelt sind
await new Promise((r) => setTimeout(r, 2000));

const report = await pc.getStats();
report.forEach((stat) => {
  if (stat.type === 'local-candidate' || stat.type === 'remote-candidate') {
    console.log(stat.type, stat.candidateType, stat.protocol, `${stat.address}:${stat.port}`);
  }
});
local-candidate host udp 3f2a9c1e-....local:54321 local-candidate srflx udp 203.0.113.7:54321

Prüfen, ob die aktive Verbindung über TURN läuft

const getConnectionType = async (pc) => {
  const report = await pc.getStats();
  let pair;
  report.forEach((s) => {
    if (s.type === 'transport' && s.selectedCandidatePairId) {
      pair = report.get(s.selectedCandidatePairId);
    }
  });
  // Fallback für Browser ohne selectedCandidatePairId (z. B. Firefox)
  if (!pair) {
    report.forEach((s) => {
      if (s.type === 'candidate-pair' && s.state === 'succeeded' && s.nominated) pair = s;
    });
  }
  if (!pair) return 'unbekannt';

  const local = report.get(pair.localCandidateId);
  const remote = report.get(pair.remoteCandidateId);
  return {
    lokal: local?.candidateType,
    entfernt: remote?.candidateType,
    relay: local?.candidateType === 'relay' || remote?.candidateType === 'relay',
    relayProtokoll: local?.relayProtocol
  };
};

// Aufruf nach erfolgreichem Verbindungsaufbau
pc.addEventListener('iceconnectionstatechange', async () => {
  if (pc.iceConnectionState === 'connected') {
    console.log(await getConnectionType(pc));
  }
});
{ lokal: 'srflx', entfernt: 'host', relay: false, relayProtokoll: undefined }

Kandidaten nach Typ zählen (Monitoring)

const countCandidates = async (pc) => {
  const counts = {};
  (await pc.getStats()).forEach((s) => {
    if (s.type === 'local-candidate') {
      counts[s.candidateType] = (counts[s.candidateType] ?? 0) + 1;
    }
  });
  return counts;
};

console.log(await countCandidates(pc));
{ host: 2, srflx: 1, relay: 1 }

// Wichtig · Fallstricke

  • Kein Konstruktor: RTCIceCandidateStats ist ein Wörterbuch, keine globale Klasse – Objekte entstehen nur über getStats(). instanceof-Prüfungen funktionieren nicht; stattdessen stat.type auswerten.
  • Datenschutz: Browser verschleiern lokale Host-Adressen oft per mDNS (xxxx.local). address kann außerdem null sein, etwa wenn die Seite keine Mediengerät-Berechtigung hat. IP-Adressen gelten als personenbezogene Daten – beim Versand an Monitoring-Server beachten.
  • Veraltete Felder: Ältere Implementierungen nutzten ip statt address, deleted und networkType; diese wurden aus der Spezifikation entfernt. Für Kompatibilität stat.address ?? stat.ip verwenden.
  • Browser-Unterschiede: Die Menge der gelieferten Felder variiert (z. B. url, relayProtocol, tcpType). selectedCandidatePairId auf dem Transport-Eintrag fehlt in Firefox – dort über nominated/selected des Kandidatenpaars suchen.
  • Zeitpunkt: Kandidaten tauchen erst nach dem ICE-Gathering im Bericht auf; getStats() direkt nach createOffer() liefert eventuell noch keine Einträge.