Signatur
Beschreibung
Der Konstruktor MediaStreamTrackGenerator() gehört zur sogenannten Insertable Streams for MediaStreamTrack-API („Breakout Box“). Er erzeugt einen Track, der sich wie jeder andere MediaStreamTrack verhält. Er kann also in einem <video>-Element angezeigt, an eine RTCPeerConnection übergeben oder mit MediaRecorder aufgenommen werden. Seine Medieninhalte stammen aber nicht von Kamera oder Mikrofon, sondern von Ihrem eigenen JavaScript-Code.
Die Daten schreiben Sie über die Eigenschaft writable ein, einen WritableStream. Bei einem Video-Track sind das VideoFrame-Objekte, bei einem Audio-Track AudioData-Objekte. Meist wird der Generator zusammen mit MediaStreamTrackProcessor verwendet: Der Processor liefert die Frames eines echten Tracks als ReadableStream, ein TransformStream verändert sie (zum Beispiel für Hintergrundunschärfe, Filter oder Wasserzeichen), und der Generator macht daraus wieder einen Track.
Typische Einsatzgebiete sind Videokonferenz-Effekte, das Einblenden von Overlays, synthetisch erzeugte Testbilder oder das Einspeisen von Frames aus WebCodecs-Decodern in eine WebRTC-Verbindung.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | object | Konfigurationsobjekt für den zu erzeugenden Track. | |
| $options.kind Pflicht | "audio" | "video" | Art des Tracks. Bei "video" nimmt writable VideoFrame-Objekte an, bei "audio" AudioData-Objekte. Andere Werte lösen einen TypeError aus. |
Rückgabewert
MediaStreamTrackGenerator-Objekt. Es erbt von MediaStreamTrack und besitzt zusätzlich die Eigenschaft writable (WritableStream).Beispiele
Kamerabild in Graustufen umwandeln (Breakout Box)
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track });
const generator = new MediaStreamTrackGenerator({ kind: 'video' });
const canvas = new OffscreenCanvas(1, 1);
const ctx = canvas.getContext('2d');
const transformer = new TransformStream({
async transform(frame, controller) {
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
ctx.filter = 'grayscale(1)';
ctx.drawImage(frame, 0, 0);
const newFrame = new VideoFrame(canvas, { timestamp: frame.timestamp });
frame.close(); // Original-Frame freigeben!
controller.enqueue(newFrame);
}
});
processor.readable.pipeThrough(transformer).pipeTo(generator.writable);
// Der Generator ist selbst ein MediaStreamTrack
document.querySelector('video').srcObject = new MediaStream([generator]);
Synthetisches Testbild erzeugen
const generator = new MediaStreamTrackGenerator({ kind: 'video' });
const writer = generator.writable.getWriter();
const canvas = new OffscreenCanvas(640, 360);
const ctx = canvas.getContext('2d');
let n = 0;
const tick = async () => {
ctx.fillStyle = `hsl(${n % 360}, 80%, 50%)`;
ctx.fillRect(0, 0, 640, 360);
ctx.fillStyle = '#fff';
ctx.font = '48px sans-serif';
ctx.fillText(`Frame ${n}`, 40, 80);
const frame = new VideoFrame(canvas, { timestamp: n * 33333 }); // µs
await writer.write(frame);
frame.close();
n++;
if (generator.readyState === 'live') setTimeout(tick, 33);
};
tick();
console.log(generator.kind, generator.readyState);
Unterstützung prüfen und Fehler bei ungültigem kind
if (!('MediaStreamTrackGenerator' in globalThis)) {
console.log('Nicht unterstützt – Fallback z. B. canvas.captureStream()');
} else {
try {
new MediaStreamTrackGenerator({ kind: 'text' });
} catch (err) {
console.log(err.name);
}
}
// Wichtig · Fallstricke
- Kompatibilität: Die API ist nicht standardisiert und nur in Chromium-Browsern (Chrome, Edge, Opera) verfügbar. Die W3C-Spezifikation ersetzt sie durch
VideoTrackGenerator, das nur in Workern verfügbar ist. Prüfen Sie die Unterstützung immer per Feature-Detection und sehen Sie einen Fallback vor, etwaHTMLCanvasElement.captureStream(). - Speicher:
VideoFrame- undAudioData-Objekte belegen oft GPU- oder Hardware-Puffer. Rufen Sie nach der Verarbeitung immerclose()auf. Sonst kommt der Stream ins Stocken, oder der Speicher läuft voll. - Der
kindmuss zu den geschriebenen Daten passen. Wer einAudioDatain einen Video-Generator schreibt, bekommt einen Fehler und der Stream bricht ab. - Verwenden Sie für die Zeitstempel (
timestamp, in Mikrosekunden) monoton steigende Werte. Sonst kann es bei der Wiedergabe oder in WebRTC zu Rucklern kommen. - Rufen Sie auf dem Generator
stop()auf, wird der Track beendet (readyState=\"ended\"), und weitere Schreibzugriffe schlagen fehl. - Rechenintensive Transformationen verlegen Sie am besten in einen Worker, damit der Hauptthread nicht blockiert.