Start · Sprachen · JavaScript · Referenz · RTCIceCandidateStats.lastPacketSentTimestamp

RTCIceCandidateStats.lastPacketSentTimestamp

Eigenschaft

Zeitpunkt (<code>DOMHighResTimeStamp</code>), zu dem über das ICE-Kandidatenpaar zuletzt ein Paket gesendet wurde. STUN-Verbindungsprüfungen zählen dabei nicht mit.

seit JavaScript WebRTC Statistics API; Unterstützung je nach Brows Kategorie: webapi

Signatur

RTCIceCandidatePairStats.lastPacketSentTimestamp

Beschreibung

Die schreibgeschützte Eigenschaft lastPacketSentTimestamp gehört zum Wörterbuch RTCIceCandidatePairStats. MDN führt sie unter RTCIceCandidateStats, gemeint ist aber das Stats-Objekt vom Typ "candidate-pair". Sie gibt an, wann die Verbindung dieses Kandidatenpaars zuletzt ein Paket gesendet hat. STUN-Pakete für Verbindungsprüfungen (Connectivity Checks) zählen nicht mit, es geht nur um Nutzdaten wie RTP, RTCP oder SCTP/DataChannel.

Den Wert liest du aus dem RTCStatsReport, den RTCPeerConnection.getStats() liefert. Er ist ein DOMHighResTimeStamp in Millisekunden und nutzt dieselbe Zeitbasis wie die Eigenschaft timestamp des Stats-Objekts. Deshalb kannst du beide Werte direkt voneinander abziehen.

Typische Einsatzfälle:

  • Stillstand erkennen: Wird der Wert über längere Zeit nicht aktualisiert, sendet die Verbindung keine Medien oder Daten mehr, etwa weil ein Track stummgeschaltet ist oder die Verbindung hängt.
  • Überwachung der Verbindungsqualität zusammen mit lastPacketReceivedTimestamp, bytesSent und currentRoundTripTime.
  • Diagnose, welches Kandidatenpaar tatsächlich Daten überträgt, z. B. das ausgewählte (nominated) Paar.

Rückgabewert

Typ
DOMHighResTimeStamp | undefined
Beschreibung
Zeitstempel in Millisekunden für das zuletzt gesendete Nicht-STUN-Paket. undefined, wenn noch kein Paket gesendet wurde oder der Browser die Eigenschaft nicht unterstützt.

Beispiele

Letzten Sendezeitpunkt des aktiven Kandidatenpaars auslesen

const getActivePair = async (pc) => {
  const report = await pc.getStats();
  let transport;
  report.forEach((s) => { if (s.type === 'transport') transport = s; });
  // Bevorzugt das vom Transport ausgewählte Paar, sonst das nominierte
  if (transport?.selectedCandidatePairId) {
    return report.get(transport.selectedCandidatePairId);
  }
  for (const s of report.values()) {
    if (s.type === 'candidate-pair' && s.nominated && s.state === 'succeeded') return s;
  }
  return undefined;
};

const pair = await getActivePair(peerConnection);
if (pair?.lastPacketSentTimestamp !== undefined) {
  const idleMs = pair.timestamp - pair.lastPacketSentTimestamp;
  console.log(`Letztes Paket vor ${idleMs.toFixed(0)} ms gesendet`);
} else {
  console.log('Kein Sendezeitpunkt verfügbar');
}
Letztes Paket vor 18 ms gesendet

Sende-Stillstand periodisch überwachen

const STALL_THRESHOLD_MS = 3000;

const watchSending = (pc) => setInterval(async () => {
  const report = await pc.getStats();
  for (const s of report.values()) {
    if (s.type !== 'candidate-pair' || !s.nominated) continue;
    const last = s.lastPacketSentTimestamp;
    if (last === undefined) continue;
    const idle = s.timestamp - last;
    if (idle > STALL_THRESHOLD_MS) {
      console.warn(`Paar ${s.id}: seit ${Math.round(idle / 1000)} s nichts gesendet`);
    }
  }
}, 1000);

const timerId = watchSending(peerConnection);
// Später: clearInterval(timerId);
Paar CPabc123_def456: seit 4 s nichts gesendet

Senden und Empfangen gegenüberstellen

const report = await peerConnection.getStats();
const pairs = [...report.values()].filter((s) => s.type === 'candidate-pair');

console.table(pairs.map((p) => ({
  id: p.id,
  state: p.state,
  nominated: p.nominated,
  bytesSent: p.bytesSent,
  lastSent: p.lastPacketSentTimestamp?.toFixed(0) ?? '–',
  lastReceived: p.lastPacketReceivedTimestamp?.toFixed(0) ?? '–'
})));
Tabelle mit allen Kandidatenpaaren und ihren letzten Sende- und Empfangszeitpunkten

// Wichtig · Fallstricke

  • Falscher Elternname: Die Eigenschaft steht auf Stats-Objekten mit type === "candidate-pair" (RTCIceCandidatePairStats), nicht auf local-candidate oder remote-candidate.
  • STUN zählt nicht: Consent-Freshness- und Connectivity-Check-Pakete aktualisieren den Wert nicht. Ein Paar kann also verbunden sein und trotzdem einen alten Zeitstempel haben.
  • Zeitbasis: Vergleiche den Wert immer mit stats.timestamp aus demselben Bericht und nicht mit Date.now(). Je nach Browser und Version kann die Zeitbasis unterschiedlich sein, z. B. Unix-Epoche oder performance.timeOrigin.
  • Kompatibilität: Chromium-Browser und Firefox unterstützen die Eigenschaft, Safari möglicherweise nur teilweise. Prüfe deshalb immer auf undefined.
  • Performance: getStats() ist asynchron und relativ aufwendig. Frage die Statistiken höchstens etwa einmal pro Sekunde ab.