Start · Sprachen · JavaScript · Referenz · RTCInboundRtpStreamStats.timestamp

RTCInboundRtpStreamStats.timestamp

Eigenschaft

Gibt als <code>DOMHighResTimeStamp</code> in Millisekunden an, wann die Statistikdaten eines eingehenden RTP-Streams erfasst wurden.

seit JavaScript Baseline: alle modernen Browser (Chrome, Edge, Fir Kategorie: webapi

Signatur

RTCInboundRtpStreamStats.timestamp

Beschreibung

Die schreibgeschützte Eigenschaft timestamp eines RTCInboundRtpStreamStats-Objekts (Eintrag mit type === "inbound-rtp" in einem RTCStatsReport) gibt an, wann die Werte in diesem Objekt erfasst wurden. Der Wert ist ein DOMHighResTimeStamp, also eine Zahl in Millisekunden (mit Nachkommastellen). Laut Spezifikation bezieht er sich auf die Unix-Epoche (1. Januar 1970, UTC).

Wichtig ist die Eigenschaft vor allem für Berechnungen über die Zeit. Kennzahlen wie bytesReceived, packetsReceived, packetsLost oder framesDecoded sind Zähler, die nur ansteigen. Eine Rate wie Bitrate, Paketverlust pro Sekunde oder Bildrate bekommt man erst, wenn man die Differenz zweier Messungen durch die Differenz ihrer timestamp-Werte teilt.

Man sollte immer timestamp aus dem Bericht verwenden und nicht die eigene Uhrzeit beim Aufruf von getStats() (z. B. Date.now()). Zwischen dem Erfassen der Werte und dem Auflösen des Promise kann einige Zeit vergehen, und Browser liefern Statistiken teilweise aus einem Zwischenspeicher.

Rückgabewert

Typ
number (DOMHighResTimeStamp)
Beschreibung
Zeitpunkt der Erfassung in Millisekunden seit der Unix-Epoche (mit Bruchteilen von Millisekunden). Schreibgeschützt.

Beispiele

Zeitstempel eines eingehenden Streams auslesen

// pc ist eine verbundene RTCPeerConnection
const logInboundTimestamps = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'inbound-rtp') {
      console.log(stats.kind, stats.timestamp, new Date(stats.timestamp).toISOString());
    }
  });
};

logInboundTimestamps(pc);
video 1718101234567.123 2024-06-11T10:20:34.567Z audio 1718101234567.123 2024-06-11T10:20:34.567Z

Empfangs-Bitrate aus zwei Messungen berechnen

const previous = new Map(); // Stats-ID -> letzte Messung

const measureBitrate = async (pc) => {
  const report = await pc.getStats();
  for (const stats of report.values()) {
    if (stats.type !== 'inbound-rtp') continue;

    const prev = previous.get(stats.id);
    if (prev) {
      const deltaMs = stats.timestamp - prev.timestamp;
      // Ohne neue Messung (Zwischenspeicher) nicht durch 0 teilen
      if (deltaMs > 0) {
        const bits = (stats.bytesReceived - prev.bytesReceived) * 8;
        const kbps = bits / deltaMs; // Bit pro ms = kbit/s
        console.log(`${stats.kind}: ${kbps.toFixed(1)} kbit/s`);
      }
    }
    previous.set(stats.id, stats);
  }
};

const timer = setInterval(() => measureBitrate(pc), 1000);
// später: clearInterval(timer);
video: 1480.3 kbit/s audio: 32.1 kbit/s

Bildrate und Paketverlustrate pro Sekunde

let last = null;

const sampleVideo = async (receiver) => {
  // Statistiken nur für einen RTCRtpReceiver abfragen
  const report = await receiver.getStats();
  const inbound = [...report.values()].find((s) => s.type === 'inbound-rtp');
  if (!inbound) return;

  if (last && inbound.timestamp > last.timestamp) {
    const seconds = (inbound.timestamp - last.timestamp) / 1000;
    const fps = (inbound.framesDecoded - last.framesDecoded) / seconds;
    const lostPerSec = (inbound.packetsLost - last.packetsLost) / seconds;
    console.log({ fps: Math.round(fps), lostPerSec: lostPerSec.toFixed(2) });
  }
  last = inbound;
};

const [videoReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'video');
setInterval(() => sampleVideo(videoReceiver), 2000);
{ fps: 30, lostPerSec: '0.50' }

// Wichtig · Fallstricke

  • Delta auf 0 prüfen: Browser speichern Statistiken teilweise kurz zwischen. Zwei schnelle getStats()-Aufrufe können deshalb denselben timestamp liefern. Vor dem Teilen immer auf deltaMs > 0 prüfen.
  • Nicht mit performance.now() mischen: Der Wert bezieht sich auf die Unix-Epoche, nicht auf performance.timeOrigin. Zum Vergleich mit performance.now() muss man performance.timeOrigin addieren. Ältere Browserversionen hatten hier teils andere Bezugspunkte. Am sichersten ist es, nur Zeitstempel aus derselben Quelle voneinander abzuziehen.
  • Nicht mit remoteTimestamp verwechseln: remoteTimestamp in RTCRemoteOutboundRtpStreamStats ist die Uhrzeit der Gegenstelle. Die ist nicht mit der lokalen Uhr abgeglichen.
  • Einträge über ihre id zuordnen: Beim Berechnen von Raten Messungen über stats.id zuordnen, nicht über ihre Position im Bericht. Wenn Streams neu verhandelt werden, können Einträge wegfallen oder neu hinzukommen.
  • Browserunterstützung: Die Eigenschaft ist in allen aktuellen Browsern mit WebRTC vorhanden. Welche anderen Felder von inbound-rtp es gibt, unterscheidet sich aber je nach Browser.