Start · Sprachen · JavaScript · Referenz · new MediaStreamTrackProcessor()

new MediaStreamTrackProcessor()

Methode

Erzeugt einen <code>MediaStreamTrackProcessor</code>, der einen <code>MediaStreamTrack</code> einliest und seine Frames als <code>ReadableStream</code> von <code>VideoFrame</code>-Objekten bereitstellt.

seit JavaScript Chromium 94+ (Window und Worker); Safari 18+ (nur Kategorie: webapi

Signatur

new MediaStreamTrackProcessor(options)

Beschreibung

Der Konstruktor MediaStreamTrackProcessor() gehört zur Spezifikation MediaStream Insertable Streams (mediacapture-transform). Er verbindet einen Live-MediaStreamTrack, etwa von einer Kamera, einer Bildschirmfreigabe oder einem Canvas-Capture, mit der WHATWG-Streams-API. Das neue Objekt hat die Eigenschaft readable, einen ReadableStream. Bei Video-Tracks liefert er VideoFrame-Objekte. In Chromium liefert er bei Audio-Tracks zusätzlich AudioData-Objekte.

Damit kannst du einzelne Frames roh verarbeiten, ohne den Umweg über <video> und <canvas>. Typische Anwendungen sind Hintergrund-Unschärfe, Filter, Bilderkennung mit ML-Modellen, das Kodieren mit VideoEncoder (WebCodecs) oder eigene Aufzeichnungs-Pipelines. Oft kombiniert man den Prozessor mit einem TransformStream und einem MediaStreamTrackGenerator bzw. VideoTrackGenerator. So entsteht aus den bearbeiteten Frames wieder ein abspielbarer Track.

Laut Spezifikation ist die Schnittstelle nur in Dedicated Workern verfügbar. So bleibt aufwendige Frame-Verarbeitung außerhalb des Haupt-Threads. Chromium stellt den Konstruktor auch im Window-Kontext bereit. Im Worker ist er trotzdem meist die bessere Wahl.

Wichtig: Jedes gelesene VideoFrame belegt knappen (GPU-)Speicher und muss mit frame.close() freigegeben werden. Liest du den Stream nicht schnell genug, verwirft der Prozessor alte Frames. Wie viele Frames höchstens gepuffert werden, legt maxBufferSize fest.

Parameter

Name Typ Default Beschreibung
$options Pflicht Object Konfigurationsobjekt mit den folgenden Eigenschaften.
$options.track Pflicht MediaStreamTrack Der Track, der verarbeitet werden soll, z. B. aus getUserMedia() oder getDisplayMedia(). Laut Spezifikation nur kind === "video"; Chromium akzeptiert auch Audio-Tracks.
$options.maxBufferSize number implementierungsabhängig (Chromium: wenige Frames) Höchstzahl gepufferter Frames. Ist der Puffer voll, werden die ältesten Frames verworfen. Größere Werte glätten Lastspitzen, erhöhen aber Latenz und Speicherbedarf.

Rückgabewert

Typ
MediaStreamTrackProcessor
Beschreibung
Ein neues MediaStreamTrackProcessor-Objekt. Seine Eigenschaft readable ist ein ReadableStream<VideoFrame> (bei Audio in Chromium ein ReadableStream<AudioData>).

Beispiele

Kamera-Frames lesen und Metadaten ausgeben (Chromium, Haupt-Thread)

const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();

const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();

let count = 0;
while (count < 5) {
  const { value: frame, done } = await reader.read();
  if (done) break;
  console.log(`Frame ${count}: ${frame.displayWidth}x${frame.displayHeight}, ts=${frame.timestamp}µs`);
  frame.close(); // Speicher sofort freigeben!
  count++;
}

reader.releaseLock();
track.stop();
Frame 0: 640x480, ts=1234567µs Frame 1: 640x480, ts=1267900µs ...

Frames in einem Worker verarbeiten (ReadableStream übertragen)

// main.js
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const { readable } = new MediaStreamTrackProcessor({ track, maxBufferSize: 2 });

const worker = new Worker('frame-worker.js');
worker.postMessage({ readable }, [readable]); // Stream ist übertragbar
worker.onmessage = (e) => console.log('Worker:', e.data);

// frame-worker.js
self.onmessage = async ({ data: { readable } }) => {
  let frames = 0;
  const started = performance.now();
  for await (const frame of readable) {
    frames++;
    frame.close();
    if (frames % 30 === 0) {
      const fps = frames / ((performance.now() - started) / 1000);
      self.postMessage(`${fps.toFixed(1)} fps`);
    }
  }
};
Worker: 29.8 fps Worker: 30.0 fps

Pipeline: Graustufen-Filter mit TransformStream und MediaStreamTrackGenerator

const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } });
const [track] = stream.getVideoTracks();

const processor = new MediaStreamTrackProcessor({ track });
const generator = new MediaStreamTrackGenerator({ kind: 'video' });

const canvas = new OffscreenCanvas(640, 480);
const ctx = canvas.getContext('2d');

const grayscale = new TransformStream({
  transform(frame, controller) {
    ctx.filter = 'grayscale(1)';
    ctx.drawImage(frame, 0, 0, canvas.width, canvas.height);
    const out = new VideoFrame(canvas, { timestamp: frame.timestamp });
    frame.close();
    controller.enqueue(out);
  }
});

processor.readable.pipeThrough(grayscale).pipeTo(generator.writable);

document.querySelector('video').srcObject = new MediaStream([generator]);