VideoFrame
The VideoFrame class represents a single frame of video, containing raw pixel data along with timing and layout metadata. VideoFrames can be created from raw pixel buffers or by cloning existing frames.
VideoFrames hold significant memory resources. You must call close() when done with a frame to release its resources. Failing to do so will cause memory leaks.
Quick Example
import { VideoFrame } from 'node-webcodecs' ;
// Create a frame from raw I420 pixel data
const width = 1920 ;
const height = 1080 ;
const i420Data = new Uint8Array ( width * height * 1.5 ); // I420 is 12 bits per pixel
const frame = new VideoFrame ( i420Data , {
format: 'I420' ,
codedWidth: width ,
codedHeight: height ,
timestamp: 0 , // Presentation time in microseconds
duration: 33333 // Frame duration (30fps = ~33333us)
});
// Access frame properties
console . log ( frame . format ); // 'I420'
console . log ( frame . codedWidth ); // 1920
console . log ( frame . codedHeight ); // 1080
console . log ( frame . timestamp ); // 0
// Copy pixel data to a buffer
const buffer = new Uint8Array ( frame . allocationSize ());
await frame . copyTo ( buffer );
// Always close when done!
frame . close ();
Constructors
VideoFrame has two constructor overloads: one for creating frames from raw pixel buffers, and one for creating frames from existing VideoFrames.
From Buffer
Creates a new VideoFrame from raw pixel data.
new VideoFrame ( data : BufferSource , init : VideoFrameBufferInit )
The raw pixel data as an ArrayBuffer or TypedArray (e.g., Uint8Array).
The data layout must match the specified format.
init
VideoFrameBufferInit
required
Configuration object for the video frame. Show VideoFrameBufferInit properties
Width of the frame in pixels, including any padding.
Height of the frame in pixels, including any padding.
Presentation timestamp in microseconds . Determines when the frame should be displayed.
Duration of the frame in microseconds . For 30fps video, this is typically 33333 (1/30 second).
Display width in pixels. Defaults to codedWidth. Use for non-square pixel aspect ratios.
Display height in pixels. Defaults to codedHeight. Use for non-square pixel aspect ratios.
The visible rectangle within the coded frame. Useful for cropping. Show visibleRect properties
X offset of the visible region.
Y offset of the visible region.
Width of the visible region.
Height of the visible region.
From Existing Frame
Creates a new VideoFrame by cloning an existing frame with optional modifications.
new VideoFrame ( image : VideoFrame , init ?: VideoFrameInit )
An existing VideoFrame to copy. The source frame’s data and metadata are copied.
Optional configuration to override properties from the source frame. Show VideoFrameInit properties
Presentation timestamp in microseconds .
Duration of the frame in microseconds .
Override the pixel format.
Override the coded width.
Override the coded height.
Override the display width.
Override the display height.
Override the visible rectangle. Show visibleRect properties
X offset of the visible region.
Y offset of the visible region.
Width of the visible region.
Height of the visible region.
Override the color space information.
Properties
All properties are readonly after construction.
format
VideoPixelFormat | null
required
The pixel format of the frame data (e.g., 'I420', 'NV12', 'RGBA').
See Pixel Formats for all supported formats.
Width of the frame in pixels, including any codec-required padding.
May be larger than displayWidth.
Height of the frame in pixels, including any codec-required padding.
May be larger than displayHeight.
Width the frame should be displayed at, accounting for pixel aspect ratio.
Use this for rendering.
Height the frame should be displayed at, accounting for pixel aspect ratio.
Use this for rendering.
Presentation timestamp in microseconds. Determines when this frame should be
displayed relative to the start of the video.
Duration of this frame in microseconds, or null if not specified during construction.
Color space information for the frame, including primaries, transfer characteristics,
and matrix coefficients. See VideoColorSpace .
visibleRect
DOMRectReadOnly | null
required
The visible portion of the frame. This defines the crop region that should be displayed.
Contains x, y, width, and height properties.
Methods
allocationSize()
Calculates the number of bytes needed to hold the frame’s pixel data.
frame . allocationSize ( options ?: VideoFrameCopyToOptions ): number
Optional configuration for the allocation calculation. Show VideoFrameCopyToOptions properties
Copy only a specific rectangular region. Custom layout for the output planes.
Convert to a different pixel format when copying.
Returns: number - The size in bytes needed for the buffer.
Example: Calculate buffer size
const frame = new VideoFrame ( data , {
format: 'I420' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: 0
});
// Full frame size
const fullSize = frame . allocationSize ();
console . log ( `Full frame: ${ fullSize } bytes` ); // ~3,110,400 bytes for I420
// Size for a cropped region
const cropSize = frame . allocationSize ({
rect: { x: 0 , y: 0 , width: 640 , height: 480 }
});
console . log ( `Cropped: ${ cropSize } bytes` );
frame . close ();
copyTo()
Copies the frame’s pixel data to a destination buffer.
frame . copyTo ( destination : BufferSource , options ?: VideoFrameCopyToOptions ): Promise < PlaneLayout [] >
An ArrayBuffer or TypedArray to copy the data into. Must have at least allocationSize() bytes available.
Optional configuration for the copy operation. See allocationSize() for options.
Returns: Promise<PlaneLayout[]> - Layout information for each plane in the output buffer.
const frame = new VideoFrame ( data , {
format: 'I420' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: 0
});
// Allocate buffer with exact size needed
const buffer = new Uint8Array ( frame . allocationSize ());
const layout = await frame . copyTo ( buffer );
// Layout describes where each plane is in the buffer
console . log ( 'Y plane:' , layout [ 0 ]); // { offset: 0, stride: 1920 }
console . log ( 'U plane:' , layout [ 1 ]); // { offset: 2073600, stride: 960 }
console . log ( 'V plane:' , layout [ 2 ]); // { offset: 2592000, stride: 960 }
frame . close ();
clone()
Creates an independent copy of this frame.
frame . clone (): VideoFrame
Returns: VideoFrame - A new VideoFrame with the same data and metadata.
Both the original and cloned frames must be closed independently. Cloning does not share resources.
const original = new VideoFrame ( data , {
format: 'RGBA' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: 0
});
// Create an independent copy
const cloned = original . clone ();
// Close original - cloned frame is still valid
original . close ();
// Use the cloned frame
console . log ( cloned . codedWidth ); // 1920
// Don't forget to close the clone too!
cloned . close ();
close()
Releases the resources held by this frame. After calling close(), the frame becomes unusable.
Always call close() when you’re done with a VideoFrame. Failure to do so will cause memory leaks, as video frames can hold significant amounts of pixel data.
Example: Proper resource management
const frame = new VideoFrame ( data , {
format: 'I420' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: 0
});
try {
// Use the frame
await processFrame ( frame );
} finally {
// Always close in a finally block
frame . close ();
}
VideoFrame supports the following pixel formats:
Format Description I420YUV 4:2:0 planar (most common) I420AI420 with alpha plane I422YUV 4:2:2 planar I444YUV 4:4:4 planar NV12YUV 4:2:0 semi-planar RGBA32-bit RGBA interleaved RGBX32-bit RGB (alpha ignored) BGRA32-bit BGRA interleaved BGRX32-bit BGR (alpha ignored)
type VideoPixelFormat =
| 'I420' // Y, U, V planes (most efficient for encoding)
| 'I420A' // Y, U, V, A planes
| 'I422' // Y, U, V planes (higher chroma resolution)
| 'I444' // Y, U, V planes (full chroma resolution)
| 'NV12' // Y plane, interleaved UV plane
| 'RGBA' // Red, Green, Blue, Alpha interleaved
| 'RGBX' // Red, Green, Blue, padding interleaved
| 'BGRA' // Blue, Green, Red, Alpha interleaved
| 'BGRX' ; // Blue, Green, Red, padding interleaved
Type Definitions
PlaneLayout
Describes the layout of a single plane in a pixel buffer.
interface PlaneLayout {
offset : number ; // Byte offset of the plane in the buffer
stride : number ; // Number of bytes per row
}
VideoFrameInit
Configuration for creating a VideoFrame from an existing frame.
interface VideoFrameInit {
timestamp : number ; // Required: microseconds
duration ?: number ; // Optional: microseconds
format ?: VideoPixelFormat ; // Optional: pixel format
codedWidth ?: number ; // Optional: coded width
codedHeight ?: number ; // Optional: coded height
displayWidth ?: number ; // Optional: display width
displayHeight ?: number ; // Optional: display height
visibleRect ?: { // Optional: visible region
x : number ;
y : number ;
width : number ;
height : number ;
};
colorSpace ?: VideoColorSpaceInit ; // Optional: color space
}
VideoFrameBufferInit
Configuration for creating a VideoFrame from raw pixel data.
interface VideoFrameBufferInit extends VideoFrameInit {
format : VideoPixelFormat ; // Required: pixel format
codedWidth : number ; // Required: coded width
codedHeight : number ; // Required: coded height
}
VideoFrameCopyToOptions
Options for allocationSize() and copyTo() methods.
interface VideoFrameCopyToOptions {
rect ?: { // Optional: copy only this region
x : number ;
y : number ;
width : number ;
height : number ;
};
layout ?: PlaneLayout []; // Optional: custom output layout
format ?: VideoPixelFormat ; // Optional: convert to this format
}
Usage with VideoEncoder
VideoFrames are typically passed to VideoEncoder.encode() for compression:
import { VideoEncoder , VideoFrame } from 'node-webcodecs' ;
const encoder = new VideoEncoder ({
output : ( chunk , metadata ) => {
console . log ( `Encoded ${ chunk . type } frame: ${ chunk . byteLength } bytes` );
},
error : ( e ) => console . error ( 'Encoding error:' , e )
});
encoder . configure ({
codec: 'avc1.42001f' , // H.264 Baseline
width: 1920 ,
height: 1080 ,
bitrate: 5_000_000
});
// Create and encode frames
for ( let i = 0 ; i < 60 ; i ++ ) {
const frame = new VideoFrame ( pixelData , {
format: 'I420' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: i * 33333 // 30fps
});
encoder . encode ( frame );
frame . close (); // Close after encoding
}
await encoder . flush ();
Usage with VideoDecoder
VideoFrames are produced by VideoDecoder when decoding encoded chunks:
import { VideoDecoder , EncodedVideoChunk } from 'node-webcodecs' ;
const decoder = new VideoDecoder ({
output : ( frame ) => {
console . log ( `Decoded: ${ frame . codedWidth } x ${ frame . codedHeight } ${ frame . format } ` );
// Copy pixel data for processing
const buffer = new Uint8Array ( frame . allocationSize ());
await frame . copyTo ( buffer );
// Always close the frame when done!
frame . close ();
},
error : ( e ) => console . error ( 'Decoding error:' , e )
});
decoder . configure ({
codec: 'avc1.42001f' ,
codedWidth: 1920 ,
codedHeight: 1080
});
decoder . decode ( encodedChunk );
await decoder . flush ();
See Also