Start · Sprachen · JavaScript · Referenz · VideoTrackGenerator.track

VideoTrackGenerator.track

Eigenschaft

Liefert den <code>MediaStreamTrack</code> vom Typ <code>"video"</code>, dessen Bilder aus den <code>VideoFrame</code>-Objekten stammen, die in <code>VideoTrackGenerator.writable</code> geschrieben werden.

seit JavaScript Experimentell: Safari 18+ (nur in Dedicated Worker Kategorie: webapi

Signatur

VideoTrackGenerator.track

Beschreibung

Die schreibgeschützte Eigenschaft track eines VideoTrackGenerator gibt den zugehörigen MediaStreamTrack zurück. Jedes VideoFrame, das in den WritableStream unter generator.writable geschrieben wird, erscheint als neues Bild in diesem Track. So erzeugen Sie aus selbst berechneten oder verarbeiteten Bildern eine normale Videospur, die sich in einem <video>-Element anzeigen, per MediaRecorder aufzeichnen oder über WebRTC (RTCPeerConnection) versenden lässt.

Typisch ist das Zusammenspiel mit MediaStreamTrackProcessor, wenn Sie Kamerabilder bearbeiten wollen (Hintergrund weichzeichnen, Filter, Wasserzeichen, Bilderkennung). Der Processor zerlegt die Kameraspur in einen ReadableStream aus VideoFrame-Objekten, ein TransformStream verarbeitet sie und der Generator setzt sie wieder zu einer Spur zusammen.

VideoTrackGenerator steht nur in Dedicated Workers zur Verfügung. Den erzeugten Track schicken Sie daher per postMessage() als übertragbares Objekt (Transfer-Liste) an den Haupt-Thread. Beim Lesen der Eigenschaft wird immer dasselbe Track-Objekt geliefert, solange es nicht übertragen wurde.

Rückgabewert

Typ
MediaStreamTrack
Beschreibung
Ein MediaStreamTrack mit kind === "video", der die in writable geschriebenen Bilder ausgibt. Mit generator.muted = true werden Bilder verworfen und der Track gilt als stummgeschaltet.

Beispiele

Kamerabilder im Worker verarbeiten und Track zurückgeben (worker.js)

// worker.js – läuft als Dedicated Worker
self.onmessage = async ({ data }) => {
  const processor = new MediaStreamTrackProcessor({ track: data.track });
  const generator = new VideoTrackGenerator();

  // Erzeugten Track an den Haupt-Thread übertragen
  self.postMessage({ track: generator.track }, [generator.track]);

  const transformer = new TransformStream({
    async transform(frame, controller) {
      // Hier könnte ein Filter per OffscreenCanvas angewendet werden
      controller.enqueue(frame);
    }
  });

  await processor.readable
    .pipeThrough(transformer)
    .pipeTo(generator.writable);
};

Verarbeiteten Track im Haupt-Thread anzeigen

// main.js
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [cameraTrack] = stream.getVideoTracks();

const worker = new Worker('worker.js');
worker.postMessage({ track: cameraTrack }, [cameraTrack]);

worker.onmessage = ({ data }) => {
  console.log(data.track.kind, data.track.readyState);
  const video = document.querySelector('video');
  video.srcObject = new MediaStream([data.track]);
  video.play();
};
video live

Synthetische Bilder aus einem OffscreenCanvas erzeugen

// worker.js
const generator = new VideoTrackGenerator();
const writer = generator.writable.getWriter();
const canvas = new OffscreenCanvas(640, 360);
const ctx = canvas.getContext('2d');

self.postMessage({ track: generator.track }, [generator.track]);

let n = 0;
setInterval(async () => {
  ctx.fillStyle = `hsl(${n % 360} 80% 50%)`;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  const frame = new VideoFrame(canvas, { timestamp: n * 33_333 });
  await writer.write(frame); // Frame gehört nun dem Generator
  n++;
}, 33);

// Wichtig · Fallstricke

  • Kompatibilität: Teil der Spezifikation MediaStreamTrack Insertable Media Processing. Derzeit nur in Safari (ab Version 18) und nur in Dedicated Workers verfügbar. Chromium-Browser bieten stattdessen das ältere, nicht standardisierte MediaStreamTrackGenerator an, das auch im Haupt-Thread läuft. Prüfen Sie per 'VideoTrackGenerator' in self, ob es vorhanden ist.
  • Nach der Übertragung per postMessage(…, [generator.track]) ist das Track-Objekt im Worker nicht mehr nutzbar. Übertragen Sie den Track deshalb nur einmal.
  • Rufen Sie track.stop() auf (bzw. beenden Sie alle Klone), endet der Track. Danach schlagen weitere Schreibvorgänge auf writable fehl. Schließen Sie Pipeline und Writer entsprechend.
  • VideoFrame-Objekte belegen oft GPU-Speicher. Bilder, die Sie verwerfen und nicht schreiben, müssen Sie mit frame.close() freigeben, sonst kann die Bildquelle (z. B. die Kamera) ins Stocken geraten.
  • Zeitstempel (timestamp in Mikrosekunden) sollten stetig ansteigen, damit Wiedergabe und Aufnahme gleichmäßig laufen.