Start · Sprachen · JavaScript · Referenz · RTCIceCandidatePairStats

RTCIceCandidatePairStats

Schnittstelle

Ein Statistik-Wörterbuch der WebRTC-API, das Qualität, Latenz und Datendurchsatz eines ICE-Kandidatenpaars einer <code>RTCPeerConnection</code> beschreibt.

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

Signatur

interface RTCIceCandidatePairStats extends RTCStats

Beschreibung

RTCIceCandidatePairStats ist ein Wörterbuch (Dictionary). Einen Konstruktor dafür gibt es nicht. Die Objekte liefert RTCPeerConnection.getStats() bzw. RTCRtpSender.getStats()/RTCRtpReceiver.getStats() im zurückgegebenen RTCStatsReport. Man erkennt sie an type === "candidate-pair". Jedes Objekt beschreibt ein Paar aus lokalem und entferntem ICE-Kandidaten, das beim Verbindungsaufbau geprüft wurde oder gerade benutzt wird.

Das Wörterbuch ist das wichtigste Werkzeug, um die tatsächlich genutzte Netzwerkverbindung zu untersuchen: Welcher Weg wurde gewählt (direkt, über STUN oder über ein TURN-Relay)? Wie hoch ist die Umlaufzeit (currentRoundTripTime)? Welche Bandbreite schätzt der Browser (availableOutgoingBitrate)? Wie viele Bytes wurden übertragen? Typische Einsatzfälle sind Verbindungsqualitäts-Anzeigen in Videokonferenzen, Monitoring und Fehlersuche bei NAT- oder Firewall-Problemen.

Wichtige Eigenschaften (zusätzlich zu id, timestamp und type aus RTCStats):

  • localCandidateId / remoteCandidateId: IDs der zugehörigen RTCIceCandidateStats-Einträge im selben Bericht.
  • transportId: ID des zugehörigen RTCTransportStats-Eintrags.
  • state: "frozen", "waiting", "in-progress", "failed" oder "succeeded".
  • nominated: true, wenn das Paar für die Nutzung nominiert wurde.
  • bytesSent, bytesReceived, packetsSent, packetsReceived: Zähler für die übertragenen Daten.
  • currentRoundTripTime, totalRoundTripTime, responsesReceived: Latenzwerte in Sekunden, ermittelt über STUN-Prüfungen.
  • availableOutgoingBitrate, availableIncomingBitrate: Bandbreitenschätzung in Bit/s.
  • requestsSent, requestsReceived, consentRequestsSent, lastPacketSentTimestamp, lastPacketReceivedTimestamp: Diagnosewerte zu Konnektivitätsprüfungen.

Das aktiv genutzte Paar findet man am zuverlässigsten über RTCTransportStats.selectedCandidatePairId. Wenn man den Transport nicht auswerten will, reicht als Näherung ein Paar mit nominated === true und state === "succeeded".

Rückgabewert

Typ
RTCIceCandidatePairStats
Beschreibung
Ein einfaches Objekt innerhalb eines RTCStatsReport (einer Map-ähnlichen Struktur). Man erhält es über await pc.getStats().

Beispiele

Alle Kandidatenpaare aus dem Statistikbericht auslesen

const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
// ... Signalisierung / Verbindungsaufbau ...

const listPairs = async () => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'candidate-pair') {
      console.log(stats.id, stats.state, 'nominiert:', stats.nominated);
    }
  });
};

await listPairs();
CPabc123_def456 succeeded nominiert: true CPxyz789_uvw012 failed nominiert: false

Aktives Paar über den Transport finden und Verbindungstyp bestimmen

const getActivePair = async (pc) => {
  const report = await pc.getStats();
  let pair = null;

  // Bevorzugter Weg: selectedCandidatePairId aus RTCTransportStats
  for (const stats of report.values()) {
    if (stats.type === 'transport' && stats.selectedCandidatePairId) {
      pair = report.get(stats.selectedCandidatePairId);
    }
  }
  // Fallback: nominiertes, erfolgreiches Paar
  pair ??= [...report.values()].find(
    (s) => s.type === 'candidate-pair' && s.nominated && s.state === 'succeeded'
  );
  if (!pair) return null;

  const local = report.get(pair.localCandidateId);
  const remote = report.get(pair.remoteCandidateId);
  return {
    lokal: `${local.candidateType} ${local.address}:${local.port} (${local.protocol})`,
    entfernt: `${remote.candidateType} ${remote.address}:${remote.port}`,
    ueberRelay: local.candidateType === 'relay' || remote.candidateType === 'relay',
    rttMs: Math.round((pair.currentRoundTripTime ?? 0) * 1000)
  };
};

console.log(await getActivePair(pc));
{ lokal: 'srflx 203.0.113.5:54321 (udp)', entfernt: 'host 192.168.1.20:50000', ueberRelay: false, rttMs: 42 }

Laufende Qualitätsanzeige: Durchsatz und Bandbreite pro Sekunde

let previous = null;

const monitor = setInterval(async () => {
  const report = await pc.getStats();
  const pair = [...report.values()].find(
    (s) => s.type === 'candidate-pair' && s.nominated && s.state === 'succeeded'
  );
  if (!pair) return;

  if (previous) {
    const seconds = (pair.timestamp - previous.timestamp) / 1000;
    const kbitIn = ((pair.bytesReceived - previous.bytesReceived) * 8) / seconds / 1000;
    const kbitOut = ((pair.bytesSent - previous.bytesSent) * 8) / seconds / 1000;
    console.log(
      `↓ ${kbitIn.toFixed(0)} kbit/s | ↑ ${kbitOut.toFixed(0)} kbit/s | ` +
      `geschätzt verfügbar: ${((pair.availableOutgoingBitrate ?? 0) / 1000).toFixed(0)} kbit/s`
    );
  }
  previous = pair;
}, 1000);

// Beim Beenden aufräumen
pc.addEventListener('connectionstatechange', () => {
  if (pc.connectionState === 'closed' || pc.connectionState === 'failed') clearInterval(monitor);
});
↓ 1480 kbit/s | ↑ 950 kbit/s | geschätzt verfügbar: 2300 kbit/s

// Wichtig · Fallstricke

  • Kein Konstruktor: RTCIceCandidatePairStats ist ein reines Wörterbuch. Man bekommt es nur über getStats(), ein new-Aufruf ist nicht möglich.
  • Nominiert ist nicht dasselbe wie aktiv: Mehrere Paare können nominated: true haben, etwa nach einem ICE-Neustart. Verlässlich ist RTCTransportStats.selectedCandidatePairId. Die veraltete Eigenschaft selected gab es nur in Firefox, man sollte sich nicht darauf verlassen.
  • Browser-Unterschiede: Nicht jeder Browser liefert jedes Feld. availableIncomingBitrate fehlt oft, und in Firefox kann auch availableOutgoingBitrate fehlen. Felder deshalb immer mit ?? oder in absichern. Veraltete Felder wie priority, readable oder writable wurden aus der Spezifikation entfernt.
  • Zähler sind kumulativ: bytesSent, totalRoundTripTime usw. wachsen immer weiter. Raten erhält man nur aus der Differenz zweier Messungen, geteilt durch die Differenz der timestamp-Werte (in Millisekunden).
  • Einheiten: Umlaufzeiten werden in Sekunden angegeben, Bitraten in Bit pro Sekunde.
  • Datenschutz: Über die verknüpften RTCIceCandidateStats lassen sich IP-Adressen auslesen. Browser verschleiern lokale Host-Adressen teils über mDNS (*.local). Statistiken, die an ein Monitoring-Backend gehen, sollte man vorher anonymisieren.
  • Performance: getStats() ist asynchron und nicht kostenlos. Intervalle unter etwa 500 ms sind selten sinnvoll.