Start · Sprachen · JavaScript · Referenz · RTCTransportStats.selectedCandidatePairChanges

RTCTransportStats.selectedCandidatePairChanges

Eigenschaft

Gibt an, wie oft das ausgewählte ICE-Kandidatenpaar dieses Transports seit Beginn der Verbindung gewechselt hat.

seit JavaScript Chrome 111+, Edge 111+, Safari 17+ (Firefox: nicht Kategorie: webapi

Signatur

RTCTransportStats.selectedCandidatePairChanges

Beschreibung

Die schreibgeschützte Eigenschaft selectedCandidatePairChanges eines RTCTransportStats-Objekts (Statistik-Typ "transport") enthält eine ganze Zahl. Sie zählt, wie oft der ICE-Agent das aktive Kandidatenpaar gewechselt hat, also die Kombination aus lokalem und entferntem Kandidaten, über die Medien und Daten tatsächlich fließen.

Ein Wechsel kommt z. B. vor, wenn während der ICE-Aushandlung ein besseres Paar gefunden wird (etwa eine direkte Host- oder srflx-Verbindung statt eines TURN-Relays), wenn ein ICE-Neustart ausgelöst wird oder wenn sich das Netzwerk ändert, zum Beispiel beim Wechsel von WLAN zu Mobilfunk. Die Initialauswahl wird dabei als erster Wechsel gezählt. Nach dem Verbindungsaufbau ist der Wert deshalb typischerweise 1.

Die Eigenschaft eignet sich vor allem für Monitoring und Fehlerdiagnose. Wenn der Zähler während einer laufenden Sitzung ständig steigt, spricht das für instabile Netzwerkpfade, Paketverluste oder Probleme mit NAT/Firewall. Solche Wechsel führen oft zu kurzen Aussetzern in Audio und Video. Den Wert liest du über RTCPeerConnection.getStats() aus. Das aktuell gewählte Paar findest du über selectedCandidatePairId.

Rückgabewert

Typ
number
Beschreibung
Eine nicht-negative ganze Zahl (unsigned long): wie oft das ausgewählte Kandidatenpaar dieses Transports insgesamt gewechselt hat.

Beispiele

Anzahl der Paarwechsel auslesen

const pc = new RTCPeerConnection();
// ... Verbindung wie üblich aufbauen (Offer/Answer, ICE) ...

const logPairChanges = async () => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'transport') {
      console.log(`Transport ${stats.id}: ${stats.selectedCandidatePairChanges ?? 'n/a'} Wechsel`);
    }
  });
};

await logPairChanges();
Transport T01: 1 Wechsel

Instabile Verbindung per Polling erkennen

const watchCandidateSwitches = (pc, intervalMs = 5000) => {
  let lastCount = null;

  const timer = setInterval(async () => {
    const report = await pc.getStats();
    for (const stats of report.values()) {
      if (stats.type !== 'transport' || stats.selectedCandidatePairChanges === undefined) continue;

      const count = stats.selectedCandidatePairChanges;
      if (lastCount !== null && count > lastCount) {
        console.warn(`Kandidatenpaar gewechselt (${count - lastCount}x in ${intervalMs / 1000}s)`);
      }
      lastCount = count;
    }
  }, intervalMs);

  // Aufräumen, sobald die Verbindung geschlossen wird
  pc.addEventListener('connectionstatechange', () => {
    if (pc.connectionState === 'closed') clearInterval(timer);
  });

  return () => clearInterval(timer);
};

const stopWatching = watchCandidateSwitches(pc);
Kandidatenpaar gewechselt (1x in 5s)

Wechselzähler zusammen mit dem aktiven Paar anzeigen

const describeTransport = async (pc) => {
  const report = await pc.getStats();
  for (const t of report.values()) {
    if (t.type !== 'transport') continue;
    const pair = report.get(t.selectedCandidatePairId);
    const local = pair && report.get(pair.localCandidateId);
    const remote = pair && report.get(pair.remoteCandidateId);
    console.log({
      wechsel: t.selectedCandidatePairChanges,
      lokal: local?.candidateType,
      entfernt: remote?.candidateType,
      rttMs: pair ? Math.round(pair.currentRoundTripTime * 1000) : null
    });
  }
};

await describeTransport(pc);
{ wechsel: 2, lokal: 'srflx', entfernt: 'host', rttMs: 34 }

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Chromium-Browser und Safari unterstützen die Eigenschaft, Firefox liefert sie derzeit nicht. Prüfe daher immer auf undefined, z. B. mit ??.
  • Der Wert ist ein kumulativer Zähler. Für Aussagen über Instabilität brauchst du die Differenz zwischen zwei Messungen, nicht den absoluten Wert.
  • Die erste Auswahl eines Paars zählt bereits als Wechsel. Ein Wert von 1 ist also normal und kein Hinweis auf ein Problem.
  • Bei bundlePolicy: "max-bundle" gibt es meist nur einen Transport. Ohne Bundling kann es mehrere "transport"-Einträge mit eigenen Zählern geben.
  • getStats() ist asynchron und nicht kostenlos. Frage die Statistik nicht in sehr kurzen Abständen ab, typisch sind 1–10 Sekunden.