Signatur
Beschreibung
Ein MediaStreamTrackProcessor macht die Frames eines MediaStreamTrack als ReadableStream von VideoFrame- bzw. AudioData-Objekten zugänglich (Eigenschaft readable). Die Quelle, etwa eine Kamera, liefert Frames in fester Rate. Liest Ihr Code sie langsamer, als sie ankommen, füllt sich der interne Puffer. Seine Größe legen Sie mit der Option maxBufferSize fest. Ist der Puffer voll, verwirft der Prozessor die ältesten Frames. Die Eigenschaft discardedFrames zählt diese verworfenen Frames.
Die Eigenschaft ist gut für Leistungsmessung und Diagnose. Sie zeigt, ob Ihre Verarbeitungskette (z. B. VideoEncoder, WebGL-Filter, maschinelles Lernen) mit der Bildrate der Quelle mithält. Steigt der Wert ständig, sollten Sie die Verarbeitung vereinfachen, die Auflösung oder Bildrate senken (track.applyConstraints()) oder die Arbeit in einen Worker auslagern.
Der Wert ist eine nicht negative ganze Zahl. Er beginnt bei 0 und steigt während der Lebensdauer des Prozessors immer nur an. Für eine Rate (verworfene Frames pro Sekunde) müssen Sie die Differenz zwischen zwei Messungen selbst berechnen.
Rückgabewert
Beispiele
Verworfene Frames bei langsamer Verarbeitung zählen
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track, maxBufferSize: 2 });
const reader = processor.readable.getReader();
// Bewusst langsamer Verbraucher: 200 ms pro Frame
for (let i = 0; i < 20; i++) {
const { value: frame, done } = await reader.read();
if (done) break;
await new Promise((r) => setTimeout(r, 200));
frame.close(); // VideoFrame immer freigeben!
}
console.log('Verworfen:', processor.discardedFrames);
track.stop();
Verwurfsrate pro Sekunde überwachen
const stream = await navigator.mediaDevices.getUserMedia({ video: { frameRate: 30 } });
const [track] = stream.getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track });
let last = 0;
const timer = setInterval(() => {
const current = processor.discardedFrames;
console.log(`Verworfen/s: ${current - last}`);
last = current;
}, 1000);
// Frames verarbeiten
const transformer = new TransformStream({
transform(frame, controller) {
// ... aufwendige Bildverarbeitung ...
controller.enqueue(frame);
}
});
const generator = new MediaStreamTrackGenerator({ kind: 'video' });
processor.readable.pipeThrough(transformer).pipeTo(generator.writable)
.finally(() => clearInterval(timer));
Automatisch Bildrate drosseln
const [track] = (await navigator.mediaDevices.getUserMedia({ video: true })).getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track });
let previous = 0;
setInterval(async () => {
const dropped = processor.discardedFrames - previous;
previous = processor.discardedFrames;
if (dropped > 5) {
const { frameRate = 30 } = track.getSettings();
await track.applyConstraints({ frameRate: Math.max(10, frameRate - 5) });
console.log('Bildrate reduziert auf', track.getSettings().frameRate);
}
}, 2000);
// Wichtig · Fallstricke
- Kompatibilität: Die Eigenschaft ist experimentell und nicht allgemein verfügbar.
MediaStreamTrackProcessorgibt es in Chromium ab Version 94. Laut Spezifikation soll er nur in Dedicated Workers verfügbar sein; Safari bietet ihn ab Version 18 nur dort an. Prüfen Sie vorher mit'discardedFrames' in processor, ob die Eigenschaft existiert. - Als standardisierte Alternative gibt es
track.stats(MediaStreamTrackVideoStats) mitdeliveredFrames,discardedFramesundtotalFrames. Diese Werte gehören zum Track, nicht zum Prozessor. - Ein großer Wert für
maxBufferSizesenkt zwar die Zahl der verworfenen Frames, erhöht aber Latenz und Speicherbedarf. Für Echtzeit-Anwendungen ist ein kleiner Puffer meist besser. - Rufen Sie
frame.close()nicht auf, wird der GPU- bzw. Kameraspeicher nicht freigegeben. Die Quelle kann dann blockieren oder noch mehr Frames verwerfen. - Der Zähler steigt nur an und wird nicht zurückgesetzt. Für Raten müssen Sie Differenzen zwischen Messungen bilden.