Signatur
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,bytesSentundcurrentRoundTripTime. - Diagnose, welches Kandidatenpaar tatsächlich Daten überträgt, z. B. das ausgewählte (
nominated) Paar.
Rückgabewert
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');
}
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);
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) ?? '–'
})));
// Wichtig · Fallstricke
- Falscher Elternname: Die Eigenschaft steht auf Stats-Objekten mit
type === "candidate-pair"(RTCIceCandidatePairStats), nicht auflocal-candidateoderremote-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.timestampaus demselben Bericht und nicht mitDate.now(). Je nach Browser und Version kann die Zeitbasis unterschiedlich sein, z. B. Unix-Epoche oderperformance.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.