Skip to main content

Overview

Hardware-accelerated video encoding uses your GPU instead of CPU to encode video, providing:
  • 8-15x faster encoding compared to software encoders
  • Lower CPU usage (typically 10-20% vs 80-100%)
  • Lower power consumption and heat generation
  • Real-time encoding of high-resolution video (4K+)
node-webcodecs supports hardware acceleration on all major platforms through FFmpeg’s hardware encoder backends.

Platform Support

macOS

VideoToolbox
  • M-series: Exceptional performance
  • Intel Macs: Good performance
  • Supports H.264, HEVC, ProRes

Windows / Linux

NVIDIA NVENC
  • GeForce GTX 600+
  • Quadro, Tesla GPUs
  • Supports H.264, HEVC

Intel Systems

Intel QuickSync
  • 2nd gen Core+ (Sandy Bridge+)
  • Supports H.264, HEVC, VP9, AV1

AMD GPUs

AMD VCE/VCN
  • Radeon HD 7000+
  • Supports H.264, HEVC

Raspberry Pi

V4L2 M2M
  • Pi 4, Pi 5
  • H.264 encoding

Quick Start

macOS (VideoToolbox)

const { VideoEncoder } = require('node-webcodecs');

const encoder = new VideoEncoder({
  output: (chunk) => { /* ... */ },
  error: (err) => console.error(err)
});

// Use VideoToolbox hardware encoder
encoder.configure({
  codec: 'h264_videotoolbox',  // ← Hardware encoder
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,
  hardwareAcceleration: 'prefer-hardware'  // Optional, but recommended
});

// That's it! Encoding now uses the GPU

Windows / Linux (NVIDIA NVENC)

encoder.configure({
  codec: 'h264_nvenc',  // ← NVIDIA hardware encoder
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,
  hardwareAcceleration: 'prefer-hardware'
});

Intel QuickSync (All Platforms)

encoder.configure({
  codec: 'h264_qsv',  // ← Intel QuickSync
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,
  hardwareAcceleration: 'prefer-hardware'
});

Hardware Encoder Codecs

H.264 Hardware Encoders

codec: 'h264_videotoolbox'

HEVC (H.265) Hardware Encoders

codec: 'hevc_videotoolbox'

Other Hardware Codecs

// VP9 (Intel QuickSync)
codec: 'vp9_qsv'

// AV1 (Intel Arc GPUs)
codec: 'av1_qsv'

// ProRes (macOS VideoToolbox)
codec: 'prores_videotoolbox'

Detecting Hardware Support

Always check if hardware acceleration is available before using it:
const { VideoEncoder } = require('node-webcodecs');

async function checkHardwareSupport() {
  const encoders = [
    { name: 'VideoToolbox (H.264)', codec: 'h264_videotoolbox' },
    { name: 'VideoToolbox (HEVC)', codec: 'hevc_videotoolbox' },
    { name: 'NVENC (H.264)', codec: 'h264_nvenc' },
    { name: 'NVENC (HEVC)', codec: 'hevc_nvenc' },
    { name: 'QuickSync (H.264)', codec: 'h264_qsv' },
    { name: 'QuickSync (HEVC)', codec: 'hevc_qsv' },
  ];

  console.log('Hardware Encoder Support:\n');

  for (const { name, codec } of encoders) {
    const result = await VideoEncoder.isConfigSupported({
      codec,
      width: 1920,
      height: 1080,
      hardwareAcceleration: 'prefer-hardware'
    });

    console.log(`${name}: ${result.supported ? '✓ Supported' : '✗ Not available'}`);
  }
}

checkHardwareSupport();
Example Output (M1 Mac):
Hardware Encoder Support:

VideoToolbox (H.264): ✓ Supported
VideoToolbox (HEVC): ✓ Supported
NVENC (H.264): ✗ Not available
NVENC (HEVC): ✗ Not available
QuickSync (H.264): ✗ Not available
QuickSync (HEVC): ✗ Not available

Graceful Fallback

Always provide a software encoder fallback:
async function createEncoder() {
  // Try hardware encoder first
  let config = {
    codec: 'h264_videotoolbox',
    width: 1920,
    height: 1080,
    bitrate: 5_000_000,
    hardwareAcceleration: 'prefer-hardware'
  };

  let support = await VideoEncoder.isConfigSupported(config);

  if (!support.supported) {
    console.log('⚠️  Hardware encoder not available, falling back to software');
    config.codec = 'avc1.42E01E';  // Software H.264
    config.hardwareAcceleration = 'prefer-software';
  }

  const encoder = new VideoEncoder({
    output: (chunk) => { /* ... */ },
    error: (err) => console.error(err)
  });

  encoder.configure(config);
  console.log(`✓ Using encoder: ${config.codec}`);

  return encoder;
}

Platform-Specific Auto-Selection

function selectHardwareEncoder() {
  const platform = process.platform;
  const arch = process.arch;

  // macOS - use VideoToolbox
  if (platform === 'darwin') {
    return 'h264_videotoolbox';
  }

  // Windows/Linux - try NVENC, then QuickSync, then software
  if (platform === 'win32' || platform === 'linux') {
    // Check for NVIDIA GPU (in a real app, detect this properly)
    return 'h264_nvenc';  // or 'h264_qsv' for Intel
  }

  // Fallback to software
  return 'avc1.42E01E';
}

const encoder = new VideoEncoder({ /* ... */ });
encoder.configure({
  codec: selectHardwareEncoder(),
  width: 1920,
  height: 1080,
  bitrate: 5_000_000
});

Performance Comparison

Real-world encoding performance (1080p30, M1 MacBook Pro):
EncoderSpeedCPU UsageQualityPower
h264_videotoolbox (HW)600 fps15%ExcellentLow
libx264 (SW)45 fps95%ExcellentHigh
h264_nvenc (NVIDIA)550 fps12%Very GoodLow
h264_qsv (Intel)400 fps18%GoodLow
Performance varies by:
  • GPU model and generation
  • Resolution and framerate
  • Encoder quality settings
  • System thermal state

Quality Settings

macOS VideoToolbox

encoder.configure({
  codec: 'h264_videotoolbox',
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,

  // Quality presets
  // Options: 'realtime', 'quality'
  latencyMode: 'quality',  // Higher quality, slower encoding

  // Bitrate mode
  // Options: 'constant', 'variable'
  bitrateMode: 'variable'  // Better quality for same bitrate
});

NVIDIA NVENC

encoder.configure({
  codec: 'h264_nvenc',
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,

  // Quality preset (speed vs quality tradeoff)
  // Options: 'p1' (fastest) to 'p7' (slowest, best quality)
  // Default: 'p4' (balanced)
  latencyMode: 'quality'  // Uses P5 internally
});

Intel QuickSync

encoder.configure({
  codec: 'h264_qsv',
  width: 1920,
  height: 1080,
  bitrate: 5_000_000,

  // Quality preset
  latencyMode: 'quality',  // vs 'realtime'
  bitrateMode: 'variable'
});

HEVC (H.265) Hardware Encoding

HEVC provides 25-50% better compression than H.264 at the same quality:
const encoder = new VideoEncoder({
  output: (chunk) => { /* ... */ },
  error: (err) => console.error(err)
});

encoder.configure({
  codec: 'hevc_videotoolbox',  // or 'hevc_nvenc', 'hevc_qsv'
  width: 3840,  // 4K
  height: 2160,
  bitrate: 15_000_000,  // 15 Mbps for 4K (vs 25-30 Mbps for H.264)
  hardwareAcceleration: 'prefer-hardware'
});
HEVC Patent LicensingHEVC requires patent licensing fees in some jurisdictions. Ensure you have proper licensing before distributing HEVC-encoded content.Browser Support: HEVC playback is limited (Safari only on most platforms).

4K and 8K Encoding

Hardware encoders excel at high-resolution encoding:
// 4K 60fps encoding
encoder.configure({
  codec: 'h264_videotoolbox',
  width: 3840,
  height: 2160,
  framerate: 60,
  bitrate: 40_000_000,  // 40 Mbps for 4K60
  hardwareAcceleration: 'prefer-hardware'
});

// 8K encoding (if supported)
encoder.configure({
  codec: 'hevc_videotoolbox',  // HEVC recommended for 8K
  width: 7680,
  height: 4320,
  framerate: 30,
  bitrate: 100_000_000,  // 100 Mbps for 8K30
  hardwareAcceleration: 'prefer-hardware'
});

Common Issues

Issue: “Encoder not found”

// Error: Unknown encoder 'h264_videotoolbox'
Solution: Check FFmpeg is compiled with hardware encoder support:
ffmpeg -encoders | grep videotoolbox
ffmpeg -encoders | grep nvenc
ffmpeg -encoders | grep qsv
If missing, reinstall FFmpeg with hardware support:
# macOS (Homebrew)
brew reinstall ffmpeg --with-videotoolbox

# Linux - compile from source with --enable-nvenc

Issue: Lower quality than expected

Hardware encoders optimize for speed. For higher quality:
encoder.configure({
  codec: 'h264_videotoolbox',
  bitrate: 8_000_000,  // ← Increase bitrate
  latencyMode: 'quality',  // ← Use quality mode
  bitrateMode: 'variable'  // ← Use VBR
});

Issue: Encoding fails on some resolutions

Some hardware encoders require dimensions to be multiples of 16 or 32:
// ❌ May fail
width: 1366, height: 768

// ✅ Pad to multiple of 16
width: 1376, height: 768

Best Practices

const support = await VideoEncoder.isConfigSupported({
  codec: 'h264_videotoolbox',
  width: 1920,
  height: 1080
});

if (!support.supported) {
  // Fallback to software encoder
}
Never assume hardware encoder availability.
// Recommended bitrates for hardware encoders
const bitrates = {
  '480p': 2_000_000,   // 2 Mbps
  '720p': 5_000_000,   // 5 Mbps
  '1080p': 8_000_000,  // 8 Mbps
  '1440p': 16_000_000, // 16 Mbps
  '4K': 40_000_000,    // 40 Mbps
};
Higher bitrates improve quality on hardware encoders.
// On macOS, monitor GPU usage:
// sudo powermetrics --samplers gpu_power

// On Linux with NVIDIA:
// nvidia-smi dmon

// On Windows:
// Task Manager > Performance > GPU
Ensure GPU encoding is actually being used.
Hardware encoding generates heat. For sustained encoding:
  • Monitor system temperature
  • Reduce framerate if overheating
  • Consider reducing resolution
  • Add cooling if needed for production systems

Next Steps