🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More β†’
Socket
Book a DemoSign in
Socket

webcodecs-encoder

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webcodecs-encoder

A TypeScript library for browser environments to encode video (H.264/AVC, VP9, VP8) and audio (AAC, Opus) using the WebCodecs API and mux them into MP4 or WebM containers with real-time streaming support. New function-first API design.

Source
npmnpm
Version
0.2.0
Version published
Weekly downloads
24
84.62%
Maintainers
1
Weekly downloads
Β 
Created
Source

WebCodecs Encoder - Function-First API

A TypeScript library to encode video (H.264/AVC, VP9, VP8) and audio (AAC, Opus) using the WebCodecs API and mux them into MP4 or WebM containers with a simple, function-first design.

πŸŽ‰ v1.0.0 Release
This is the stable release with the new function-first API. The API is now simplified and production-ready with automatic configuration, quality presets, and progressive enhancement.

Features

  • πŸš€ Function-First API: Simple encode(), encodeStream(), and canEncode() functions
  • 🎯 Zero Configuration: Automatic resolution, frame rate, and codec detection
  • πŸ“Š Quality Presets: Simple low, medium, high, lossless presets
  • πŸ”„ Multiple Input Types: Frame arrays, AsyncIterable, MediaStream, VideoFile
  • ⚑ Real-time Streaming: Progressive encoding with encodeStream()
  • 🎨 Progressive Enhancement: Start simple, add complexity as needed
  • πŸ”§ Transparent Worker Management: No manual worker setup required
  • πŸ“¦ Optimized Bundle Size: Import only what you need
  • πŸ›‘οΈ Type Safety: Full TypeScript support with comprehensive types
  • 🎡 Audio Support: AAC and Opus encoding with automatic configuration

Installation

npm install webcodecs-encoder
# or
yarn add webcodecs-encoder

No additional setup required! The library automatically manages Web Workers internally.

Quick Start

Basic Encoding

import { encode } from 'webcodecs-encoder';

// Encode frames with automatic configuration
const frames = [/* VideoFrame, Canvas, ImageData objects */];
const mp4Data = await encode(frames, { quality: 'medium' });

// Save or use the encoded MP4
const blob = new Blob([mp4Data], { type: 'video/mp4' });
const url = URL.createObjectURL(blob);

Streaming Encoding

import { encodeStream } from 'webcodecs-encoder';

// Real-time encoding for live streaming
const stream = await navigator.mediaDevices.getUserMedia({ video: true });

for await (const chunk of encodeStream(stream, { quality: 'high' })) {
  // Send chunk to MediaSource, server, or save incrementally
  mediaSource.appendBuffer(chunk);
}

Check Browser Support

import { canEncode } from 'webcodecs-encoder';

// Check if encoding is supported
const isSupported = await canEncode();

// Check specific configuration
const canEncodeHEVC = await canEncode({
  video: { codec: 'hevc' },
  quality: 'high'
});

API Reference

Core Functions

encode(source, options?)

Encode video to a complete MP4/WebM file.

async function encode(
  source: VideoSource,
  options?: EncodeOptions
): Promise<Uint8Array>

encodeStream(source, options?)

Stream encoding with real-time chunks.

async function* encodeStream(
  source: VideoSource,
  options?: EncodeOptions
): AsyncGenerator<Uint8Array>

canEncode(options?)

Check if encoding is supported with given options.

async function canEncode(options?: EncodeOptions): Promise<boolean>

Video Sources

The API supports multiple input types:

type VideoSource = 
  | Frame[]                    // Static frame array
  | AsyncIterable<Frame>       // Dynamic frame generation
  | MediaStream               // Camera/screen capture
  | VideoFile;                // Existing video file

type Frame = VideoFrame | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | ImageData;

Encode Options

interface EncodeOptions {
  // Basic settings (auto-detected if not specified)
  width?: number;
  height?: number;
  frameRate?: number;

  // Quality preset (recommended)
  quality?: 'low' | 'medium' | 'high' | 'lossless';

  // Advanced settings
  video?: {
    codec?: 'avc' | 'hevc' | 'vp9' | 'vp8' | 'av1';
    bitrate?: number;
    hardwareAcceleration?: 'no-preference' | 'prefer-hardware' | 'prefer-software';
    latencyMode?: 'quality' | 'realtime';
    keyFrameInterval?: number;
  };
  
  audio?: {
    codec?: 'aac' | 'opus';
    bitrate?: number;
    sampleRate?: number;
    channels?: number;
    bitrateMode?: 'constant' | 'variable';
  } | false; // false to disable audio

  container?: 'mp4' | 'webm';

  // Callbacks
  onProgress?: (progress: ProgressInfo) => void;
  onError?: (error: EncodeError) => void;
}

Usage Examples

1. Canvas Animation to MP4

import { encode } from 'webcodecs-encoder';

// Create animation frames
const frames = [];
const canvas = new OffscreenCanvas(800, 600);
const ctx = canvas.getContext('2d');

for (let i = 0; i < 120; i++) { // 4 seconds at 30fps
  ctx.clearRect(0, 0, 800, 600);
  ctx.fillStyle = `hsl(${i * 3}, 70%, 50%)`;
  ctx.fillRect(i * 6, 200, 100, 200);
  frames.push(canvas.transferToImageBitmap());
}

// Encode with automatic settings
const mp4 = await encode(frames, { 
      quality: 'high',
  frameRate: 30 
});

// Save the file
const blob = new Blob([mp4], { type: 'video/mp4' });
    const url = URL.createObjectURL(blob);
const a = document.createElement('a');
    a.href = url;
a.download = 'animation.mp4';
    a.click();

2. Camera Recording with Progress

import { encode } from 'webcodecs-encoder';

const stream = await navigator.mediaDevices.getUserMedia({ 
  video: { width: 1280, height: 720 },
  audio: true 
});

const mp4 = await encode(stream, {
  quality: 'medium',
  container: 'mp4',
  onProgress: (progress) => {
    console.log(`Progress: ${progress.percent.toFixed(1)}%`);
    console.log(`Speed: ${progress.fps.toFixed(1)} fps`);
      if (progress.estimatedRemainingMs) {
      console.log(`ETA: ${(progress.estimatedRemainingMs / 1000).toFixed(1)}s`);
    }
  }
});

3. Real-time Streaming

import { encodeStream } from 'webcodecs-encoder';

const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const chunks = [];

for await (const chunk of encodeStream(stream, { 
  quality: 'medium',
  video: { latencyMode: 'realtime' }
})) {
  // Send to server or MediaSource immediately
  chunks.push(chunk);
  
  // Or stream to MediaSource Extensions
  if (mediaSource.readyState === 'open') {
    sourceBuffer.appendBuffer(chunk);
  }
}

// Combine all chunks for final file
const fullVideo = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
let offset = 0;
for (const chunk of chunks) {
  fullVideo.set(chunk, offset);
  offset += chunk.length;
}

4. Custom Frame Generation

import { encode } from 'webcodecs-encoder';

// Generate frames dynamically
async function* generateFrames() {
  const canvas = new OffscreenCanvas(640, 480);
  const ctx = canvas.getContext('2d');
  
  for (let frame = 0; frame < 300; frame++) { // 10 seconds at 30fps
    // Draw your animation
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, 640, 480);
    ctx.fillStyle = '#fff';
    ctx.font = '48px Arial';
    ctx.fillText(`Frame ${frame}`, 50, 240);
    
    yield canvas.transferToImageBitmap();
    
    // Optional: add timing control
    await new Promise(resolve => setTimeout(resolve, 33)); // ~30fps
  }
}

const mp4 = await encode(generateFrames(), {
  quality: 'high',
  frameRate: 30
});

Advanced Usage

Custom Encoder Factory

For repeated encoding with the same settings:

import { createEncoder, encoders } from 'webcodecs-encoder/factory';

// Create custom encoder
const myEncoder = createEncoder({
  quality: 'high',
  video: { codec: 'avc' },
  audio: { codec: 'aac', bitrate: 192_000 }
});

// Use multiple times
const video1 = await myEncoder.encode(frames1);
const video2 = await myEncoder.encode(frames2);

// Or use predefined encoders
const youtubeVideo = await encoders.youtube.encode(frames);
const twitterVideo = await encoders.twitter.encode(frames);

Platform-Specific Optimization

import { examples } from 'webcodecs-encoder/factory';

// Optimize for specific platforms
const youtubeEncoder = examples.getEncoderForPlatform('youtube');
const twitterEncoder = examples.getEncoderForPlatform('twitter');

// Resolution-based optimization
const hdEncoder = examples.createByResolution(1920, 1080);
const mobileEncoder = examples.createByResolution(640, 480);

// File size constraints
const smallFileEncoder = examples.createForFileSize(10, 60); // 10MB for 60 seconds

Error Handling

import { encode, EncodeError } from 'webcodecs-encoder';

try {
  const mp4 = await encode(frames, { quality: 'high' });
  } catch (error) {
  if (error instanceof EncodeError) {
    switch (error.type) {
      case 'not-supported':
        console.log('WebCodecs not supported in this browser');
        break;
      case 'invalid-input':
        console.log('Invalid input frames or configuration');
        break;
      case 'encoding-failed':
        console.log('Encoding process failed:', error.message);
        break;
      default:
        console.log('Unknown encoding error:', error.message);
    }
  }
}

Browser Support

  • Chrome 94+: Full support
  • Edge 94+: Full support
  • Firefox: Experimental support (enable dom.media.webcodecs.enabled)
  • Safari: Not yet supported

Check support at runtime:

import { canEncode } from 'webcodecs-encoder';

const supported = await canEncode();
if (!supported) {
  // Fallback to MediaRecorder or other solutions
}

Performance Tips

  • Use quality presets instead of manual bitrate calculation
  • Enable hardware acceleration when available: { video: { hardwareAcceleration: 'prefer-hardware' } }
  • Use streaming for large videos: encodeStream() instead of encode()
  • Optimize frame rate for your use case (30fps is usually sufficient)
  • Consider container format: MP4 for compatibility, WebM for smaller files

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please see our Contributing Guide for details.

Support

Keywords

webcodecs

FAQs

Package last updated on 28 May 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts