VideoEncoder
The VideoEncoder class encodes raw VideoFrame objects into compressed EncodedVideoChunk objects. It supports multiple codecs including H.264, H.265/HEVC, VP8, VP9, and AV1, with optional hardware acceleration.
This class implements the W3C WebCodecs VideoEncoder specification . Hardware acceleration is available via platform-specific encoders (VideoToolbox on macOS, NVENC on NVIDIA GPUs, QuickSync on Intel).
Quick Example
import { VideoEncoder , VideoFrame } from 'node-webcodecs' ;
// Create encoder with output callback
const encoder = new VideoEncoder ({
output : ( chunk , metadata ) => {
console . log ( `Encoded ${ chunk . type } frame: ${ chunk . byteLength } bytes` );
// Save decoder config on first keyframe
if ( metadata ?. decoderConfig ) {
console . log ( 'Codec:' , metadata . decoderConfig . codec );
}
},
error : ( err ) => console . error ( 'Encoding error:' , err )
});
// Configure for H.264 at 1080p
encoder . configure ({
codec: 'avc1.42E01E' ,
width: 1920 ,
height: 1080 ,
bitrate: 5_000_000 ,
framerate: 30
});
// Encode frames
const frame = new VideoFrame ( rgbaBuffer , {
format: 'RGBA' ,
codedWidth: 1920 ,
codedHeight: 1080 ,
timestamp: 0
});
encoder . encode ( frame );
frame . close (); // Always close frames after encoding!
await encoder . flush ();
encoder . close ();
Hardware Acceleration Example
Use platform-specific codec names for hardware-accelerated encoding:
// Check for hardware encoder support
const hwSupport = await VideoEncoder . isConfigSupported ({
codec: 'h264_videotoolbox' , // macOS VideoToolbox
width: 1920 ,
height: 1080 ,
hardwareAcceleration: 'prefer-hardware'
});
if ( hwSupport . supported ) {
encoder . configure ({
codec: 'h264_videotoolbox' ,
width: 1920 ,
height: 1080 ,
bitrate: 10_000_000
});
} else {
// Fallback to software encoder
encoder . configure ({
codec: 'avc1.42E01E' ,
width: 1920 ,
height: 1080 ,
bitrate: 10_000_000
});
}
Codec Reference
Codec WebCodecs String Hardware Options H.264 avc1.42E01Eh264_videotoolbox, h264_nvencH.265 hvc1.1.6.L93.B0hevc_videotoolbox, hevc_nvencVP8 vp8- VP9 vp09.00.10.08- AV1 av01.0.04M.08-
Constructor
Creates a new VideoEncoder with output and error callbacks.
new VideoEncoder ( init : VideoEncoderInit )
Initialization callbacks for handling encoded output and errors. Show VideoEncoderInit properties
output
(chunk: EncodedVideoChunk, metadata?: VideoEncoderOutputMetadata) => void
required
Callback invoked for each encoded chunk. The first keyframe includes decoderConfig in metadata.
error
(error: DOMException) => void
required
Callback invoked when an encoding error occurs.
Throws: TypeError if callbacks are not functions.
Example: Creating an encoder
const chunks : EncodedVideoChunk [] = [];
let decoderConfig : VideoDecoderConfig | null = null ;
const encoder = new VideoEncoder ({
output : ( chunk , metadata ) => {
chunks . push ( chunk );
// Capture decoder config from first keyframe
if ( metadata ?. decoderConfig ) {
decoderConfig = metadata . decoderConfig ;
}
},
error : ( err ) => {
console . error ( 'Encoding failed:' , err . message );
}
});
Properties
Current encoder state. One of:
'unconfigured' - Not yet configured, or reset() was called
'configured' - Ready to encode frames
'closed' - Encoder has been closed and cannot be used
Number of pending encode operations in the queue. Useful for implementing backpressure to prevent memory exhaustion when encoding faster than output can be processed.
Methods
isConfigSupported()
Static method to check if a configuration is supported before creating an encoder.
static VideoEncoder . isConfigSupported ( config : VideoEncoderConfig ): Promise < VideoEncoderSupport >
config
VideoEncoderConfig
required
Configuration to test for support.
Returns: Promise<VideoEncoderSupport> with supported boolean and normalized config.
Example: Checking codec support
// Check software encoder support
const result = await VideoEncoder . isConfigSupported ({
codec: 'avc1.42E01E' ,
width: 1920 ,
height: 1080
});
if ( result . supported ) {
console . log ( 'H.264 encoding is supported' );
}
// Check hardware encoder with fallback
const hwResult = await VideoEncoder . isConfigSupported ({
codec: 'h264_videotoolbox' ,
width: 3840 ,
height: 2160 ,
hardwareAcceleration: 'prefer-hardware'
});
const codec = hwResult . supported ? 'h264_videotoolbox' : 'avc1.42E01E' ;
Configures the encoder with codec parameters. Must be called before encoding frames.
encoder . configure ( config : VideoEncoderConfig ): void
config
VideoEncoderConfig
required
Encoder configuration specifying codec, dimensions, bitrate, and other parameters. Show VideoEncoderConfig properties
Codec identifier. Use WebCodecs MIME types (e.g., 'avc1.42E01E') or FFmpeg codec names (e.g., 'h264_videotoolbox').
Frame width in pixels. Must be greater than 0.
Frame height in pixels. Must be greater than 0.
Display width for pixel aspect ratio correction. Defaults to width.
Display height for pixel aspect ratio correction. Defaults to height.
Target bitrate in bits per second. Example: 5_000_000 for 5 Mbps.
Target framerate in frames per second. Defaults to 30.
Hardware acceleration preference:
'no-preference' - Let encoder decide (default)
'prefer-hardware' - Use hardware if available
'prefer-software' - Force software encoding
Encoding latency optimization:
'quality' - Optimize for compression ratio (default)
'realtime' - Optimize for low latency
Bitrate control mode:
'constant' - Constant bitrate (CBR)
'variable' - Variable bitrate (VBR)
'quantizer' - Constant quality (CQP)
Alpha channel handling:
'discard' - Remove alpha channel
'keep' - Preserve alpha (if codec supports it)
SVC/temporal layering mode. Example: 'L1T2' for 1 spatial layer, 2 temporal layers.
Color space metadata including primaries, transfer, matrix, and fullRange.
H.264-specific options. Output format:
'annexb' - Annex B format with start codes (default)
'avc' - AVC format with length-prefixed NALUs
Use async encoding via worker thread. Defaults to true. Set to false for synchronous encoding (blocks event loop).
Throws:
DOMException if encoder is closed
DOMException if codec is not supported
DOMException if dimensions are invalid
Example: Basic configuration
encoder . configure ({
codec: 'avc1.42E01E' ,
width: 1920 ,
height: 1080 ,
bitrate: 5_000_000 ,
framerate: 30
});
Example: HDR encoding with VP9
encoder . configure ({
codec: 'vp09.00.10.08' ,
width: 3840 ,
height: 2160 ,
bitrate: 20_000_000 ,
colorSpace: {
primaries: 'bt2020' ,
transfer: 'pq' ,
matrix: 'bt2020-ncl'
}
});
encode()
Encodes a video frame. The frame is queued for encoding and the output callback is invoked when complete.
encoder . encode ( frame : VideoFrame , options ?: VideoEncoderEncodeOptions ): void
The VideoFrame to encode.
options
VideoEncoderEncodeOptions
Optional encoding parameters. Show VideoEncoderEncodeOptions properties
Force this frame to be a keyframe (I-frame). Keyframes are independently decodable.
Defaults to false.
Throws:
DOMException if encoder is not configured
DOMException if frame is invalid or closed
Always call frame.close() after encoding to prevent memory leaks! The encoder takes a snapshot of the frame data, so the original frame can be closed immediately after encode() returns.
Example: Encoding with keyframe control
// Force keyframes at regular intervals (every 2 seconds at 30fps)
for ( let i = 0 ; i < frames . length ; i ++ ) {
const isKeyFrame = i % 60 === 0 ; // Keyframe every 60 frames
encoder . encode ( frames [ i ], { keyFrame: isKeyFrame });
frames [ i ]. close (); // MUST close to prevent memory leak
}
flush()
Waits for all pending encode operations to complete.
encoder . flush (): Promise < void >
Returns: Promise<void> that resolves when all frames have been encoded.
Throws:
DOMException if encoder is not configured
DOMException if an encoding error occurs
Example: Flushing before close
// Encode all frames
for ( const frame of frames ) {
encoder . encode ( frame );
frame . close ();
}
// Wait for all encodes to complete
await encoder . flush ();
console . log ( 'All frames encoded!' );
encoder . close ();
reset()
Resets the encoder to unconfigured state, aborting any pending operations.
Throws: DOMException if encoder is closed.
Example: Reconfiguring encoder
encoder . configure ({ codec: 'avc1.42E01E' , width: 1920 , height: 1080 });
encoder . encode ( frame1 );
frame1 . close ();
// Abort and reconfigure with different settings
encoder . reset ();
encoder . configure ({ codec: 'vp09.00.10.08' , width: 1280 , height: 720 });
encoder . encode ( frame2 );
frame2 . close ();
close()
Closes the encoder and releases all resources. The encoder cannot be used after calling close().
try {
for ( const frame of frames ) {
encoder . encode ( frame );
frame . close ();
}
await encoder . flush ();
} finally {
encoder . close (); // Always close to release resources
}
addEventListener()
Adds an event listener for encoder events.
encoder . addEventListener ( type : string , listener : () => void , options ?: { once? : boolean }): void
Event type. Currently only 'dequeue' is supported.
Callback to invoke when the event fires.
If true, the listener is removed after being invoked once.
removeEventListener()
Removes an event listener.
encoder . removeEventListener ( type : string , listener : () => void ): void
Backpressure Management
When encoding video faster than it can be output (e.g., writing to disk), use encodeQueueSize and dequeue events to implement backpressure:
const MAX_QUEUE_SIZE = 10 ;
async function encodeWithBackpressure ( frames : VideoFrame []) {
for ( const frame of frames ) {
// Wait if queue is too large
while ( encoder . encodeQueueSize >= MAX_QUEUE_SIZE ) {
await new Promise < void >( resolve => {
encoder . addEventListener ( 'dequeue' , resolve , { once: true });
});
}
encoder . encode ( frame );
frame . close ();
}
await encoder . flush ();
}
The dequeue event fires whenever a frame completes encoding, reducing encodeQueueSize. This allows you to throttle input to prevent unbounded memory growth.
Interfaces
VideoEncoderConfig
Configuration options for the encoder.
interface VideoEncoderConfig {
codec : string ; // Required
width : number ; // Required
height : number ; // Required
displayWidth ?: number ;
displayHeight ?: number ;
bitrate ?: number ;
framerate ?: number ;
hardwareAcceleration ?: HardwareAcceleration ;
alpha ?: AlphaOption ;
scalabilityMode ?: string ;
bitrateMode ?: BitrateMode ;
latencyMode ?: LatencyMode ;
colorSpace ?: VideoColorSpaceInit ;
avc ?: { format ?: 'annexb' | 'avc' };
useWorkerThread ?: boolean ;
}
VideoEncoderInit
Callbacks for encoder initialization.
interface VideoEncoderInit {
output : ( chunk : EncodedVideoChunk , metadata ?: VideoEncoderOutputMetadata ) => void ;
error : ( error : DOMException ) => void ;
}
Metadata returned with encoded chunks.
interface VideoEncoderOutputMetadata {
decoderConfig ?: {
codec : string ;
codedWidth : number ;
codedHeight : number ;
description ?: ArrayBuffer ; // Codec extradata (SPS/PPS for H.264)
};
svc ?: {
temporalLayerId : number ; // 0 = base layer
};
}
VideoEncoderEncodeOptions
Options for encoding a single frame.
interface VideoEncoderEncodeOptions {
keyFrame ?: boolean ; // Force keyframe (default: false)
}
VideoEncoderSupport
Result from isConfigSupported().
interface VideoEncoderSupport {
supported : boolean ;
config : VideoEncoderConfig ;
}
Type Aliases
LatencyMode
type LatencyMode = 'quality' | 'realtime' ;
Value Description 'quality'Optimize for compression ratio (may buffer frames) 'realtime'Optimize for low latency encoding
BitrateMode
type BitrateMode = 'constant' | 'variable' | 'quantizer' ;
Value Description 'constant'Constant bitrate (CBR) - consistent file size 'variable'Variable bitrate (VBR) - better quality/size ratio 'quantizer'Constant quality (CQP) - consistent visual quality
AlphaOption
type AlphaOption = 'discard' | 'keep' ;
Value Description 'discard'Remove alpha channel from output 'keep'Preserve alpha channel (codec must support transparency)
See Also