Signatur
Beschreibung
Die Eigenschaft transportId eines RTCIceCandidateStats-Eintrags (Typ "local-candidate" oder "remote-candidate") enthält einen String. Dieser String entspricht der id des RTCTransportStats-Eintrags, der die Daten zu diesem Kandidaten liefert. Beide Einträge stehen im selben RTCStatsReport, den RTCPeerConnection.getStats() zurückgibt.
Mit transportId ordnet man einen Kandidaten dem zugrunde liegenden DTLS/ICE-Transport zu. Das ist vor allem nützlich, wenn mehrere Transporte existieren, etwa ohne bundlePolicy: "max-bundle" oder mit getrennten Transporten für Audio, Video und Datenkanäle. Über den Transport kommt man an den gewählten Kandidatenpaar-Eintrag (selectedCandidatePairId), den DTLS-Status und die übertragenen Bytes.
Die ID ist ein Schlüssel im RTCStatsReport. Man kann den Transport also direkt mit report.get(candidate.transportId) nachschlagen. Der Inhalt der ID hängt vom Browser ab (zum Beispiel "T01" in Chrome) und sollte nicht ausgewertet werden.
Rückgabewert
id des zugehörigen RTCTransportStats-Eintrags im selben RTCStatsReport. In einer Momentaufnahme ist sie eindeutig; über mehrere getStats()-Aufrufe bleibt sie für dasselbe Objekt normalerweise gleich.Beispiele
Kandidaten mit ihrem Transport verknüpfen
const logCandidateTransports = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'local-candidate' || stats.type === 'remote-candidate') {
const transport = report.get(stats.transportId);
console.log(
`${stats.type} ${stats.address}:${stats.port} (${stats.candidateType})`,
'→ Transport', stats.transportId,
'DTLS:', transport?.dtlsState
);
}
});
};
// Aufruf, sobald die Verbindung steht
pc.addEventListener('connectionstatechange', () => {
if (pc.connectionState === 'connected') logCandidateTransports(pc);
});
Kandidaten nach Transport gruppieren
const candidatesByTransport = async (pc) => {
const report = await pc.getStats();
const groups = new Map();
for (const stats of report.values()) {
if (!stats.type.endsWith('-candidate')) continue;
const list = groups.get(stats.transportId) ?? [];
list.push(`${stats.type}:${stats.candidateType}`);
groups.set(stats.transportId, list);
}
return groups;
};
const groups = await candidatesByTransport(pc);
console.log(Object.fromEntries(groups));
Prüfen, ob ein Kandidat zum aktiven Paar gehört
const activeCandidates = async (pc) => {
const report = await pc.getStats();
const result = [];
for (const stats of report.values()) {
if (stats.type !== 'local-candidate') continue;
const transport = report.get(stats.transportId);
const pair = transport && report.get(transport.selectedCandidatePairId);
if (pair?.localCandidateId === stats.id) {
result.push({ address: stats.address, type: stats.candidateType, protocol: stats.protocol });
}
}
return result;
};
console.log(await activeCandidates(pc));
// Wichtig · Fallstricke
- Nur im selben Bericht gültig: Die ID verweist auf einen Eintrag desselben
RTCStatsReport. Wenn man sie mit dem Ergebnis eines anderengetStats()-Aufrufs abgleicht, kann das fehlschlagen, weil sich Transporte zwischendurch ändern können, etwa durch ICE-Restart oder Neuverhandlung. - Nicht auswerten: Das Format der ID ist nicht festgelegt und unterscheidet sich zwischen Browsern. Man sollte sie nur als Schlüssel verwenden.
- Fehlender Transport: Rechne damit, dass
report.get(transportId)undefinedzurückgibt. Nutze deshalb optionale Verkettung (?.). Ältere Firefox-Versionen haben Transport-Statistiken nur teilweise geliefert. - Bundling: Mit
bundlePolicy: "max-bundle"teilen sich meist alle Kandidaten denselben Transport. Ohne Bundling können mehrere verschiedenetransportId-Werte vorkommen. - Datenschutz: Kandidaten-Statistiken können lokale IP-Adressen enthalten. Moderne Browser verbergen sie oft hinter mDNS-Namen (
*.local). Protokolliere solche Daten nur zurückhaltend.