Skip to main content
Helios supports a wide range of output formats and codecs through FFmpeg and WebCodecs, allowing you to optimize for quality, file size, or compatibility.

Video containers

MP4

Most widely supported container format:
const renderer = new Renderer({
  videoCodec: 'libx264',
  pixelFormat: 'yuv420p'
});

await renderer.render(url, './output.mp4');
Compatible codecs:
  • H.264 (libx264, h264_nvenc, h264_qsv, h264_videotoolbox)
  • H.265 (libx265, hevc_nvenc, hevc_qsv, hevc_videotoolbox)
  • AV1 (libaom-av1, libsvtav1)

WebM

Open source container for web delivery:
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  audioCodec: 'libvorbis'
});

await renderer.render(url, './output.webm');
Compatible codecs:
  • VP8 (libvpx)
  • VP9 (libvpx-vp9)
  • AV1 (libaom-av1)

MOV

QuickTime format, useful for intermediate files:
const renderer = new Renderer({
  videoCodec: 'prores',
  audioCodec: 'pcm_s16le'
});

await renderer.render(url, './output.mov');
Compatible codecs:
  • ProRes (prores, prores_ks)
  • DNxHD (dnxhd)
  • PCM audio (pcm_s16le, pcm_s24le)

Video codecs

H.264 (libx264)

Best compatibility and hardware support:
const renderer = new Renderer({
  videoCodec: 'libx264',
  preset: 'medium',
  crf: 23,  // 0-51, lower = better quality
  pixelFormat: 'yuv420p'
});
preset
string
default:"'medium'"
Encoding speed vs compression ratio:
  • 'ultrafast': Fastest encoding, largest file
  • 'superfast', 'veryfast', 'faster', 'fast'
  • 'medium': Balanced
  • 'slow', 'slower', 'veryslow': Smaller file, slower encoding
crf
number
default:"23"
Constant Rate Factor (quality):
  • 0: Lossless (huge files)
  • 18-23: High quality (recommended)
  • 23-28: Good quality
  • 28-35: Lower quality (smaller files)
  • 51: Lowest quality
tune
string
Optimize for specific content:
  • 'film': Feature film content
  • 'animation': Animated content
  • 'grain': Preserve grain
  • 'stillimage': Slideshow content

H.265 (libx265)

Better compression than H.264, but slower encoding:
const renderer = new Renderer({
  videoCodec: 'libx265',
  preset: 'medium',
  crf: 28,  // Use higher CRF than H.264 for similar quality
  pixelFormat: 'yuv420p'
});
H.265 achieves similar quality to H.264 at ~50% smaller file size, but:
  • Encoding is 5-10x slower
  • Requires modern players (may not work on older devices)
  • Patent licensing issues in some regions

VP9 (libvpx-vp9)

Royalty-free codec for web delivery:
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  crf: 30,
  videoBitrate: '2M',  // Target bitrate
  audioCodec: 'libvorbis'
});

await renderer.render(url, './output.webm');
VP9 options:
  • Similar quality to H.265
  • Better than H.264 at low bitrates
  • Native support in all modern browsers
  • Slower encoding than H.264

AV1 (libaom-av1)

Next-generation codec with best compression:
const renderer = new Renderer({
  videoCodec: 'libaom-av1',
  crf: 30,
  preset: 'fast',  // AV1 encoding is VERY slow
  pixelFormat: 'yuv420p'
});
AV1 encoding is extremely slow. A 10-second 1080p video can take 30+ minutes even on fast hardware. Use only when file size is critical.
Consider using libsvtav1 for faster AV1 encoding:
const renderer = new Renderer({
  videoCodec: 'libsvtav1',
  crf: 30,
  preset: '8'  // 0-13, higher = faster
});

Hardware-accelerated codecs

NVIDIA NVENC

Fast encoding on NVIDIA GPUs:
const renderer = new Renderer({
  hwAccel: 'cuda',
  videoCodec: 'h264_nvenc',
  preset: 'p4',  // p1-p7, higher = better quality
  videoBitrate: '5M'
});
NVENC presets:
  • 'p1': Fastest
  • 'p4': Balanced
  • 'p7': Best quality
Also available: hevc_nvenc for H.265

Intel Quick Sync (QSV)

Hardware encoding on Intel CPUs:
const renderer = new Renderer({
  hwAccel: 'qsv',
  videoCodec: 'h264_qsv',
  preset: 'medium'
});
Also available: hevc_qsv, vp9_qsv

Apple VideoToolbox

Hardware encoding on macOS:
const renderer = new Renderer({
  hwAccel: 'videotoolbox',
  videoCodec: 'h264_videotoolbox',
  videoBitrate: '5M'
});
Also available: hevc_videotoolbox, prores_videotoolbox

AMD VCE/VCN

Hardware encoding on AMD GPUs:
const renderer = new Renderer({
  hwAccel: 'vaapi',  // On Linux
  videoCodec: 'h264_vaapi'
});

Audio codecs

AAC

Most compatible audio codec:
const renderer = new Renderer({
  audioCodec: 'aac',
  audioBitrate: '192k'  // 128k, 192k, 256k, 320k
});
Recommended bitrates:
  • '128k': Good quality
  • '192k': High quality (recommended)
  • '256k': Very high quality
  • '320k': Maximum quality (overkill for most uses)

Opus

Best quality per bitrate for WebM:
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  audioCodec: 'libopus',
  audioBitrate: '128k'
});
Opus is more efficient than AAC at the same bitrate.

Vorbis

Open source codec for WebM:
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  audioCodec: 'libvorbis',
  audioBitrate: '192k'
});

PCM (uncompressed)

Lossless audio for intermediate files:
const renderer = new Renderer({
  audioCodec: 'pcm_s16le'  // 16-bit PCM
});
Also available:
  • 'pcm_s24le': 24-bit PCM (higher quality)
  • 'pcm_s32le': 32-bit PCM
  • 'pcm_f32le': 32-bit float PCM

Pixel formats

yuv420p

Standard format, widest compatibility:
const renderer = new Renderer({
  pixelFormat: 'yuv420p'
});
Limitations:
  • No alpha channel
  • 4:2:0 chroma subsampling

yuv444p

Full chroma resolution:
const renderer = new Renderer({
  pixelFormat: 'yuv444p'
});
Benefits:
  • No chroma subsampling
  • Better color fidelity
  • Larger file size

yuva420p

With alpha channel:
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  pixelFormat: 'yuva420p'
});
Alpha channel requires specific codecs (VP8, VP9, PNG). H.264 does not support alpha.

Common presets

High quality for archival

const renderer = new Renderer({
  videoCodec: 'libx265',
  preset: 'slow',
  crf: 18,
  pixelFormat: 'yuv420p',
  audioCodec: 'aac',
  audioBitrate: '256k'
});

Fast encoding for previews

const renderer = new Renderer({
  videoCodec: 'libx264',
  preset: 'ultrafast',
  crf: 28,
  audioCodec: 'aac',
  audioBitrate: '128k'
});

Web optimized (small file size)

const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  crf: 32,
  videoBitrate: '1M',
  audioCodec: 'libopus',
  audioBitrate: '96k'
});

await renderer.render(url, './output.webm');

Hardware accelerated (NVIDIA)

const renderer = new Renderer({
  hwAccel: 'cuda',
  videoCodec: 'h264_nvenc',
  preset: 'p4',
  videoBitrate: '5M',
  audioCodec: 'aac',
  audioBitrate: '192k'
});

Transparent video

const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  pixelFormat: 'yuva420p',
  mode: 'canvas',
  intermediateVideoCodec: 'vp8',  // VP8 supports alpha
  audioCodec: 'libvorbis'
});

await renderer.render(url, './output.webm');

Stream copy mode

Skip re-encoding for faster processing:
const renderer = new Renderer({
  videoCodec: 'copy',  // Copy video stream without re-encoding
  mode: 'canvas',
  intermediateVideoCodec: 'avc1.4d002a'  // Must match final codec
});
When using videoCodec: 'copy', the intermediate codec must match the desired output codec. WebCodecs must be enabled (canvas mode).
Use stream copy when:
  • Adding/removing audio tracks
  • Trimming video
  • Changing container format
Do not use when:
  • Changing resolution
  • Changing codec
  • Burning in subtitles

Bitrate control

Constant Rate Factor (CRF)

Quality-based encoding:
const renderer = new Renderer({
  videoCodec: 'libx264',
  crf: 23  // Target quality, file size varies
});
Best for:
  • Variable content complexity
  • Archival
  • When quality is more important than file size

Constant Bitrate (CBR)

Fixed bitrate:
const renderer = new Renderer({
  videoCodec: 'libx264',
  videoBitrate: '5M'  // Exact bitrate, quality varies
});
Best for:
  • Streaming
  • Predictable file sizes
  • Broadcast requirements

Two-pass encoding

For CBR, FFmpeg can use two-pass encoding (not currently exposed in Helios API):
# Pass 1
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 1 -f null /dev/null

# Pass 2
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 2 output.mp4

Format recommendations

For web delivery

// Modern browsers
const renderer = new Renderer({
  videoCodec: 'libvpx-vp9',
  crf: 30,
  audioCodec: 'libopus',
  audioBitrate: '128k'
});
await renderer.render(url, './output.webm');

For social media

// Instagram, TikTok, YouTube
const renderer = new Renderer({
  width: 1080,
  height: 1920,  // Vertical video
  videoCodec: 'libx264',
  preset: 'medium',
  crf: 23,
  pixelFormat: 'yuv420p',
  audioCodec: 'aac',
  audioBitrate: '192k'
});

For broadcast/professional

// ProRes for editing
const renderer = new Renderer({
  videoCodec: 'prores_ks',
  profile: 2,  // ProRes 422
  audioCodec: 'pcm_s24le'
});
await renderer.render(url, './output.mov');

For maximum compatibility

// Works everywhere, including old devices
const renderer = new Renderer({
  videoCodec: 'libx264',
  preset: 'medium',
  crf: 23,
  pixelFormat: 'yuv420p',
  audioCodec: 'aac',
  audioBitrate: '128k'
});
await renderer.render(url, './output.mp4');

Build docs developers (and LLMs) love