Start · Sprachen · JavaScript · Referenz · VideoFrame.allocationSize()

VideoFrame.allocationSize()

Methode

Gibt zurück, wie viele Bytes ein Puffer mindestens haben muss, damit <code>VideoFrame.copyTo()</code> die Pixeldaten des Frames mit denselben Optionen hineinkopieren kann.

seit JavaScript WebCodecs – Chrome/Edge 94+, Firefox 130+, Safari Kategorie: webapi

Signatur

VideoFrame.prototype.allocationSize(options)

Beschreibung

allocationSize() berechnet, wie viele Bytes die Pixeldaten eines VideoFrame brauchen, wenn man sie mit copyTo() in einen ArrayBuffer, ein TypedArray oder eine DataView kopiert. Die Methode sieht sich dafür das Pixelformat an (etwa I420, NV12, RGBA, BGRA), außerdem die Farbebenen (Planes), ihre Unterabtastung und die übergebenen Optionen.

Man ruft sie typischerweise direkt vor copyTo() auf, um einen passend großen Zielpuffer anzulegen. Das kommt vor, wenn man Rohpixel an WebAssembly übergeben, per postMessage() weiterreichen, analysieren oder selbst weiterverarbeiten will. Damit die Größe stimmt, übergibt man an allocationSize() und copyTo() dasselbe Optionsobjekt.

Mit rect kopiert man nur einen Bildausschnitt. Mit layout legt man für jede Ebene einen eigenen Versatz (offset) und eine eigene Zeilenlänge in Bytes (stride) fest, z. B. mit Auffüllbytes für Speicherausrichtung. In neueren Implementierungen lassen format und colorSpace eine Umwandlung nach RGB zu. Die berechnete Größe richtet sich dann nach dem Zielformat.

Parameter

Name Typ Default Beschreibung
$options object {} Optionales Objekt, das beschreibt, wie kopiert werden soll. Es muss mit den Optionen des späteren copyTo()-Aufrufs übereinstimmen.
$options.rect DOMRectInit visibleRect des Frames Ausschnitt { x, y, width, height }, der kopiert werden soll. Bei unterabgetasteten Formaten wie I420 müssen die Werte zur Unterabtastung passen (meist gerade Zahlen).
$options.layout Array<{ offset: number, stride: number }> dicht gepackt Ein Eintrag pro Farbebene: offset ist der Startversatz in Bytes, stride die Bytes pro Zeile. Die Anzahl der Einträge muss der Anzahl der Ebenen des Formats entsprechen.
$options.format "RGBA" | "RGBX" | "BGRA" | "BGRX" Format des Frames Zielformat für eine Umwandlung nach RGB beim Kopieren. Neuere Ergänzung der Spezifikation, noch nicht überall unterstützt.
$options.colorSpace "srgb" | "display-p3" "srgb" Ziel-Farbraum für die RGB-Umwandlung. Gilt nur zusammen mit format.

Rückgabewert

Typ
number
Beschreibung
Die nötige Puffergröße in Bytes (ganze Zahl). Sie deckt alle Ebenen ab, einschließlich der Versätze und Zeilenlängen aus layout.

Beispiele

Puffer passender Größe anlegen und Pixel kopieren

// I420-Frame aus Rohdaten erzeugen (Y + U + V)
const width = 1920;
const height = 1080;
const raw = new Uint8Array(width * height * 1.5);

const frame = new VideoFrame(raw, {
  format: 'I420',
  codedWidth: width,
  codedHeight: height,
  timestamp: 0,
});

const size = frame.allocationSize();
console.log('Benötigte Bytes:', size);

const buffer = new Uint8Array(size);
const layout = await frame.copyTo(buffer);
console.log(layout);

frame.close(); // Speicher sofort freigeben
Benötigte Bytes: 3110400 [{offset: 0, stride: 1920}, {offset: 2073600, stride: 960}, {offset: 2592000, stride: 960}]

Nur einen Bildausschnitt kopieren

const frame = new VideoFrame(new Uint8Array(1280 * 720 * 1.5), {
  format: 'I420',
  codedWidth: 1280,
  codedHeight: 720,
  timestamp: 0,
});

// Dasselbe Optionsobjekt für allocationSize() und copyTo() verwenden!
const options = { rect: { x: 0, y: 0, width: 320, height: 240 } };

const size = frame.allocationSize(options);
const crop = new Uint8Array(size);
await frame.copyTo(crop, options);

console.log(size); // 320*240 + 2 * (160*120)
frame.close();
115200

Eigenes Layout mit ausgerichteten Zeilen (Stride)

const frame = new VideoFrame(new Uint8Array(100 * 100 * 4), {
  format: 'RGBA',
  codedWidth: 100,
  codedHeight: 100,
  timestamp: 0,
});

// Zeilen auf 512 Bytes auffüllen (100 px * 4 B = 400 B Nutzdaten)
const options = { layout: [{ offset: 0, stride: 512 }] };

console.log(frame.allocationSize());        // dicht gepackt
console.log(frame.allocationSize(options)); // mit Auffüllbytes

const buf = new ArrayBuffer(frame.allocationSize(options));
await frame.copyTo(buf, options);
frame.close();
40000 51200

Kamerabild als RGBA auslesen (mit Rückfallebene)

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

const { value: frame } = await reader.read();
const options = { format: 'RGBA', colorSpace: 'srgb' };

let size;
try {
  size = frame.allocationSize(options); // RGB-Umwandlung (neuere Browser)
} catch (err) {
  console.warn('RGB-Umwandlung nicht unterstützt:', err.name);
  delete options.format;
  delete options.colorSpace;
  size = frame.allocationSize();
}

const pixels = new Uint8Array(size);
await frame.copyTo(pixels, options);
console.log(frame.format, frame.displayWidth, frame.displayHeight, size);

frame.close();
track.stop();
z. B.: NV12 1280 720 3686400