Start · Sprachen · JavaScript · Referenz · RTCOutboundRtpStreamStats.timestamp

RTCOutboundRtpStreamStats.timestamp

Eigenschaft

Liefert als <code>DOMHighResTimeStamp</code> den Zeitpunkt, zu dem die Statistikdaten eines ausgehenden RTP-Streams erfasst wurden.

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

Signatur

RTCOutboundRtpStreamStats.timestamp

Beschreibung

Die schreibgeschützte Eigenschaft timestamp eines RTCOutboundRtpStreamStats-Objekts gibt an, wann die Werte dieses Statistik-Eintrags erfasst wurden. Der Wert ist ein DOMHighResTimeStamp, also eine Zahl in Millisekunden, gemessen ab der UNIX-Epoche (1. Januar 1970, UTC). Er kann Nachkommastellen haben.

Solche Objekte bekommst du über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(). Sie stehen im zurückgegebenen RTCStatsReport unter dem Typ "outbound-rtp". Die Eigenschaft wird vom Basis-Wörterbuch RTCStats geerbt. Deshalb haben auch alle anderen Statistik-Typen (z. B. inbound-rtp oder candidate-pair) einen timestamp.

In der Praxis brauchst du timestamp vor allem, um Raten zu berechnen. Zähler wie bytesSent, packetsSent oder framesEncoded steigen nur an. Erst wenn du den Unterschied zweier Messungen durch den zeitlichen Abstand ihrer timestamp-Werte teilst, erhältst du Bitrate, Paketrate oder Bildrate. Das ist genauer, als mit dem Zeitpunkt des eigenen setInterval-Aufrufs zu rechnen, weil der Browser die Daten nicht genau dann erfasst, wenn du sie abfragst.

Rückgabewert

Typ
number (DOMHighResTimeStamp)
Beschreibung
Der Zeitpunkt der Erfassung in Millisekunden seit der UNIX-Epoche. Der Wert kann Nachkommastellen haben und ist schreibgeschützt.

Beispiele

Zeitstempel aller ausgehenden RTP-Streams ausgeben

// pc ist eine bestehende, verbundene RTCPeerConnection
const logOutboundTimestamps = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'outbound-rtp') {
      const zeit = new Date(stats.timestamp).toISOString();
      console.log(`${stats.kind} (SSRC ${stats.ssrc}) erfasst um ${zeit}`);
    }
  });
};

await logOutboundTimestamps(pc);
video (SSRC 1234567890) erfasst um 2024-05-14T09:31:12.482Z audio (SSRC 987654321) erfasst um 2024-05-14T09:31:12.482Z

Sende-Bitrate aus zwei Messungen berechnen

const getOutboundVideo = async (sender) => {
  const report = await sender.getStats();
  return [...report.values()].find((s) => s.type === 'outbound-rtp');
};

const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
let vorher = await getOutboundVideo(sender);

setInterval(async () => {
  const jetzt = await getOutboundVideo(sender);
  if (!jetzt || !vorher) return;

  const deltaMs = jetzt.timestamp - vorher.timestamp;
  const deltaBytes = jetzt.bytesSent - vorher.bytesSent;
  if (deltaMs > 0) {
    const kbps = (deltaBytes * 8) / deltaMs; // Bit pro ms = kbit/s
    console.log(`Sende-Bitrate: ${kbps.toFixed(1)} kbit/s`);
  }
  vorher = jetzt;
}, 1000);
Sende-Bitrate: 1487.3 kbit/s Sende-Bitrate: 1512.9 kbit/s

Bildrate beim Kodieren messen und veraltete Daten erkennen

let letzte = null;

const pruefeEncoder = async () => {
  const report = await pc.getStats();
  const out = [...report.values()].find(
    (s) => s.type === 'outbound-rtp' && s.kind === 'video'
  );
  if (!out) return;

  if (letzte && out.timestamp === letzte.timestamp) {
    console.log('Keine neuen Statistikdaten (Cache des Browsers)');
    return;
  }
  if (letzte) {
    const sekunden = (out.timestamp - letzte.timestamp) / 1000;
    const fps = (out.framesEncoded - letzte.framesEncoded) / sekunden;
    console.log(`Kodierte Bilder pro Sekunde: ${fps.toFixed(1)}`);
  }
  letzte = out;
};

setInterval(pruefeEncoder, 2000);
Kodierte Bilder pro Sekunde: 29.8

// Wichtig · Fallstricke

  • Bezugspunkt: Der Wert zählt ab der UNIX-Epoche, nicht ab performance.timeOrigin. Du kannst ihn also direkt an new Date() übergeben. Mit performance.now() kannst du ihn dagegen nicht direkt vergleichen.
  • Caching: Browser speichern Statistiken für kurze Zeit zwischen (in Chrome ungefähr bis zu 50 ms). Zwei schnell aufeinanderfolgende Aufrufe von getStats() können deshalb denselben timestamp liefern. Prüfe vor dem Teilen immer, ob deltaMs > 0 ist, sonst teilst du durch null.
  • Nur Differenzen zwischen denselben Objekten: Vergleiche nur Einträge mit derselben id bzw. ssrc. Bei Simulcast gibt es mehrere outbound-rtp-Einträge, einen pro Ebene. Nach einer Neuverhandlung können außerdem die Zähler neu beginnen.
  • Genauigkeit: Wegen des Schutzes vor Timing-Angriffen kann die Auflösung vergröbert sein. Für Raten im Sekundenbereich spielt das keine Rolle.
  • Kompatibilität: Die Eigenschaft funktioniert in allen aktuellen Browsern. Ältere Chrome-Versionen haben mit der veralteten, auf Rückruffunktionen basierenden Variante von getStats() ein anderes Format geliefert. Nutze die Promise-Variante.