Signatur
Beschreibung
Die Eigenschaft framesAssembledFromMultiplePackets eines RTCInboundRtpStreamStats-Objekts (Statistiktyp "inbound-rtp") gibt an, wie viele korrekt decodierte Frames dieses RTP-Streams aus mehr als einem RTP-Paket zusammengesetzt werden mussten. Der Wert ist ein fortlaufender Zähler, der seit Beginn des Streams nur steigt.
Frames, die in ein einzelnes Paket passen (typisch bei kleinen Delta-Frames mit niedriger Auflösung), werden nicht mitgezählt. Große Frames – etwa Keyframes oder hochaufgelöstes Video – werden dagegen auf mehrere Pakete verteilt und müssen vom Empfänger wieder zusammengesetzt werden. Genau diese Frames erfasst der Zähler.
Seine eigentliche Stärke spielt der Wert im Zusammenspiel mit totalAssemblyTime aus: Teilt man totalAssemblyTime durch framesAssembledFromMultiplePackets, erhält man die durchschnittliche Zeit zwischen dem Eintreffen des ersten und des letzten Pakets eines Frames. So lassen sich Netzwerk-Jitter, Paketverzögerungen und Engpässe beim Empfang diagnostizieren.
Die Eigenschaft ist nur für Video-Streams definiert (kind === "video"). Bei Audio-Streams fehlt sie.
Rückgabewert
unsigned long) der aus mehreren Paketen zusammengesetzten, erfolgreich decodierten Frames. undefined bei Audio-Streams oder in Browsern, die die Kennzahl nicht unterstützen.Beispiele
Zähler aus den Empfangsstatistiken auslesen
// pc ist eine verbundene RTCPeerConnection mit eingehendem Video
const logAssembledFrames = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'inbound-rtp' && stats.kind === 'video') {
console.log(
`Frames aus mehreren Paketen: ${stats.framesAssembledFromMultiplePackets ?? 'nicht verfügbar'}`
);
}
});
};
await logAssembledFrames(pc);
Durchschnittliche Zusammensetzungszeit pro Frame berechnen
const getAverageAssemblyTime = async (receiver) => {
const report = await receiver.getStats();
for (const stats of report.values()) {
if (stats.type !== 'inbound-rtp') continue;
const { framesAssembledFromMultiplePackets: frames, totalAssemblyTime } = stats;
if (!frames || totalAssemblyTime === undefined) return null;
// totalAssemblyTime ist in Sekunden angegeben
return (totalAssemblyTime / frames) * 1000;
}
return null;
};
const [videoReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'video');
const avgMs = await getAverageAssemblyTime(videoReceiver);
console.log(avgMs !== null ? `Ø Zusammensetzung: ${avgMs.toFixed(2)} ms` : 'Keine Daten');
Intervall-Werte (Delta) statt Gesamtsumme überwachen
let previous = null;
const monitor = setInterval(async () => {
const report = await pc.getStats();
const video = [...report.values()].find(
(s) => s.type === 'inbound-rtp' && s.kind === 'video'
);
if (!video || video.framesAssembledFromMultiplePackets === undefined) return;
if (previous) {
const frames = video.framesAssembledFromMultiplePackets - previous.frames;
const time = video.totalAssemblyTime - previous.time;
const avg = frames > 0 ? ((time / frames) * 1000).toFixed(2) : '–';
console.log(`Letzte Sekunde: ${frames} Frames, Ø ${avg} ms`);
}
previous = {
frames: video.framesAssembledFromMultiplePackets,
time: video.totalAssemblyTime,
};
}, 1000);
// Später beenden: clearInterval(monitor);
// Wichtig · Fallstricke
- Kompatibilität: Die Kennzahl wird derzeit vor allem von Chromium-basierten Browsern (Chrome, Edge, Opera) geliefert. In Firefox und Safari kann sie fehlen – immer auf
undefinedprüfen, z. B. mit??. - Nur Video: Bei
kind === "audio"ist die Eigenschaft nicht vorhanden. - Kumulativer Zähler: Der Wert wächst seit Streambeginn. Für aussagekräftige Live-Werte die Differenz zweier Messungen bilden (siehe Beispiel 3).
- Division durch null: Solange noch kein Frame aus mehreren Paketen zusammengesetzt wurde, ist der Wert
0– bei der Berechnung mittotalAssemblyTimevorher abfangen. - Nur korrekt decodierte Frames zählen; verworfene oder fehlerhafte Frames tauchen hier nicht auf (siehe dafür
framesDropped).