Signatur
Beschreibung
Die schreibgeschützte Eigenschaft timestamp eines RTCRemoteOutboundRtpStreamStats-Objekts (Statistiktyp "remote-outbound-rtp") ist ein DOMHighResTimeStamp in Millisekunden. Sie gibt an, wann die Daten im Statistikobjekt aufgezeichnet wurden. Ein "remote-outbound-rtp"-Eintrag beschreibt den Sender auf der Gegenseite. Seine Werte stammen aus RTCP-Sender-Reports, die die Gegenseite schickt. Deshalb bezieht sich timestamp auf die lokale Uhr: Es ist der Zeitpunkt, an dem die Werte hier erzeugt oder empfangen wurden.
Wie bei allen RTCStats-Einträgen wird der Wert laut Spezifikation relativ zur UNIX-Epoche (1. Januar 1970, UTC) angegeben. Er lässt sich also direkt mit Date.now() oder performance.timeOrigin + performance.now() vergleichen.
Wofür man ihn braucht:
- Raten berechnen: Aus der Differenz der
timestamp-Werte zweier Abfragen und der Differenz von Zählern wiebytesSentoderpacketsSentergibt sich die Bitrate oder Paketrate der Gegenseite. - Aktualität prüfen: Neue RTCP-Sender-Reports kommen nur in Abständen von einigen Sekunden. Bleibt
timestampgleich, sind die Daten seit der letzten Abfrage nicht neu. - Vergleich mit
remoteTimestamp:remoteTimestampist der Zeitpunkt, zu dem die Gegenseite den Bericht nach ihrer Uhr gesendet hat.timestampist der lokale Zeitpunkt.
Rückgabewert
Beispiele
Zeitstempel der Remote-Outbound-Statistik auslesen
// pc ist eine verbundene RTCPeerConnection
const logRemoteOutbound = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'remote-outbound-rtp') {
const zeit = new Date(stats.timestamp).toISOString();
console.log(`${stats.kind}: Daten vom ${zeit}`);
}
});
};
await logRemoteOutbound(pc);
Sende-Bitrate der Gegenseite aus zwei Messungen berechnen
const findRemoteOutbound = async (pc, kind) => {
const report = await pc.getStats();
return [...report.values()].find(
(s) => s.type === 'remote-outbound-rtp' && s.kind === kind
);
};
const messeBitrate = async (pc, kind = 'video') => {
const a = await findRemoteOutbound(pc, kind);
await new Promise((r) => setTimeout(r, 5000));
const b = await findRemoteOutbound(pc, kind);
if (!a || !b) return null;
const dtSek = (b.timestamp - a.timestamp) / 1000;
if (dtSek <= 0) return null; // kein neuer RTCP-Sender-Report
const kbit = ((b.bytesSent - a.bytesSent) * 8) / dtSek / 1000;
return Math.round(kbit);
};
console.log(`Gegenseite sendet ca. ${await messeBitrate(pc)} kbit/s`);
Alter der Daten und Vergleich mit remoteTimestamp
const pruefeAktualitaet = async (pc) => {
const report = await pc.getStats();
for (const s of report.values()) {
if (s.type !== 'remote-outbound-rtp') continue;
const alterMs = Date.now() - s.timestamp;
const differenz = s.remoteTimestamp !== undefined
? (s.timestamp - s.remoteTimestamp).toFixed(1)
: 'unbekannt';
console.log(`${s.kind}: ${alterMs.toFixed(0)} ms alt, lokal - remote = ${differenz} ms`);
}
};
setInterval(() => pruefeAktualitaet(pc), 2000);
// Wichtig · Fallstricke
- Lokale Uhr statt Uhr der Gegenseite:
timestampbezieht sich auf die lokale Uhr,remoteTimestampauf die Uhr der Gegenseite. Die Differenz der beiden ist nicht die Laufzeit im Netz, denn die Uhren beider Seiten sind nicht synchronisiert. - Seltene Aktualisierung: Remote-Statistiken beruhen auf RTCP-Sender-Reports, die typischerweise nur alle paar Sekunden eintreffen. Wer öfter abfragt, bekommt womöglich denselben
timestampmehrfach. Vor dem Teilen durch die Zeitdifferenz sollte man deshalb prüfen, ob sie größer als 0 ist. - Zeitbasis: Laut Spezifikation ist der Wert relativ zur UNIX-Epoche. Manche ältere Browser haben ihn anders geliefert. Vor einem direkten Vergleich mit
performance.now()sollte man die Zeitbasis prüfen. MitDate.now()ist man meist auf der sicheren Seite. - Verfügbarkeit:
"remote-outbound-rtp"-Einträge gibt es erst, wenn eine Verbindung besteht und der erste RTCP-Sender-Report eingetroffen ist. Direkt nach dem Verbindungsaufbau können sie fehlen. - Die Eigenschaft ist schreibgeschützt. Jeder Aufruf von
getStats()liefert neue Objekte, die gespeicherten Werte ändern sich nicht nachträglich.