Signatur
Beschreibung
Die Eigenschaft timestamp des Wörterbuchs RTCTransportStats gibt den Zeitpunkt an, zu dem der Browser die Statistikwerte des Transports erfasst hat. Ein Transport ist die ICE-/DTLS-Verbindung, über die eine RTCPeerConnection Medien und Daten überträgt. Den Wert erbt das Wörterbuch vom Basis-Wörterbuch RTCStats. Er ist ein DOMHighResTimeStamp, also eine Gleitkommazahl in Millisekunden. Laut Spezifikation bezieht er sich auf die UNIX-Epoche (1. Januar 1970, UTC).
Ohne timestamp lassen sich Zähler wie bytesSent, bytesReceived oder packetsSent kaum sinnvoll auswerten. Diese Zähler steigen seit dem Aufbau der Verbindung immer weiter an. Eine Rate wie Bitrate oder Pakete pro Sekunde erhält man erst, wenn man zwei Messungen vergleicht und die Differenz der Zähler durch die Differenz der Zeitstempel teilt.
Die Eigenschaft ist schreibgeschützt. Man erreicht sie über RTCPeerConnection.getStats(), das einen RTCStatsReport liefert. Darin gehören alle Einträge mit type === "transport" zu RTCTransportStats.
Rückgabewert
Beispiele
Zeitstempel der Transport-Statistik auslesen
// pc ist eine bereits verbundene RTCPeerConnection
const logTransportTimestamp = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === "transport") {
const date = new Date(stats.timestamp);
console.log(`Transport ${stats.id} erfasst am ${date.toISOString()}`);
}
});
};
logTransportTimestamp(pc);
Sende-Bitrate aus zwei Messungen berechnen
const getTransport = async (pc) => {
const report = await pc.getStats();
return [...report.values()].find((s) => s.type === "transport");
};
const measureBitrate = async (pc, intervalMs = 1000) => {
const first = await getTransport(pc);
await new Promise((r) => setTimeout(r, intervalMs));
const second = await getTransport(pc);
// Zeitdifferenz aus den Zeitstempeln, nicht aus intervalMs
const deltaSeconds = (second.timestamp - first.timestamp) / 1000;
const deltaBits = (second.bytesSent - first.bytesSent) * 8;
const kbps = deltaBits / deltaSeconds / 1000;
console.log(`Sende-Bitrate: ${kbps.toFixed(1)} kbit/s`);
return kbps;
};
measureBitrate(pc);
Laufendes Monitoring mit Erkennung zu alter Werte
let last = null;
const monitor = setInterval(async () => {
const report = await pc.getStats();
const t = [...report.values()].find((s) => s.type === "transport");
if (!t) return;
if (last && t.timestamp === last.timestamp) {
console.warn("Statistik wurde nicht aktualisiert (zwischengespeicherter Wert)");
return;
}
if (last) {
const dt = (t.timestamp - last.timestamp) / 1000;
const rx = ((t.bytesReceived - last.bytesReceived) * 8) / dt / 1000;
console.log(`Empfang: ${rx.toFixed(1)} kbit/s (Intervall ${dt.toFixed(3)} s)`);
}
last = t;
}, 2000);
// Beim Beenden des Gesprächs:
// clearInterval(monitor);
// Wichtig · Fallstricke
- Zeitbasis: Laut Spezifikation bezieht sich der Wert auf die UNIX-Epoche und passt damit zu
Date.now(). Ältere Browserversionen haben teilweise andere Bezugspunkte verwendet. Vergleiche den Wert daher nicht direkt mitperformance.now(). Am sichersten sind Differenzen zwischen zweitimestamp-Werten aus derselben Quelle. - Raten nicht aus dem Timer berechnen:
setTimeoutundsetIntervalsind ungenau und werden in Hintergrund-Tabs gedrosselt. Nimm für Raten immer die Differenz dertimestamp-Werte. - Zwischenspeicherung: Browser können Statistiken kurzzeitig zwischenspeichern. Sehr schnell aufeinanderfolgende
getStats()-Aufrufe liefern dann denselbentimestamp. Die Zeitdifferenz ist in diesem Fall 0, und eine Rate daraus wäre eine Division durch null. - Browserunterstützung: Nicht jeder Browser liefert Einträge vom Typ
"transport"mit allen Feldern. Firefox liefert manche Transport-Zähler nicht oder erst in neueren Versionen. Prüfe deshalb, ob der Eintrag und die Felder vorhanden sind, bevor du rechnest. - Der Wert ist schreibgeschützt. Jeder Aufruf von
getStats()erzeugt ein neues Snapshot-Objekt, das sich danach nicht mehr ändert.