Skip to content

Convert videos with alpha channels into highly optimized web-ready formats. This tool implements Jake Archibald's stacked alpha method, achieving 60-85% smaller file sizes than native transparency formats while maintaining perfect cross-browser compatibility.

License

Notifications You must be signed in to change notification settings

dparksy/stacked-alpha-converter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stacked Alpha Video Converter

The Problem: You need transparent videos in your web app. You export from Blender/After Effects with alpha, drop it in your React project, and... it works in Chrome but breaks in Safari. Or the files are 10MB+ for a 5-second loop. You try VP9 with alpha, HEVC with alpha, AVIF sequences - nothing works reliably everywhere.

The Solution: This tool converts alpha videos using Jake Archibald's stacked alpha method - a brilliant technique that delivers 60-85% smaller files with perfect cross-browser compatibility, including Safari/iOS.

Why this exists: I built this while working on a React project that needed transparent video animations. After hitting WebKit limitations and finding Jake's work, I automated the conversion process so others don't have to fight with FFmpeg commands.


Quick Start

1. Install FFmpeg

# macOS
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

# Windows (Chocolatey)
choco install ffmpeg

2. Export Your Video

Export from your video editor with an alpha channel:

  • Recommended: QuickTime Animation codec (RGBA)
  • Best quality: ProRes 4444
  • Alternative: PNG sequence

See EXPORTING.md for After Effects, Blender, Premiere Pro, and other tools.

3. Convert

./scripts/convert-alpha-videos.sh input-video.mov

This generates two files:

  • input-video_stacked_av1.mp4 (modern browsers)
  • input-video_stacked_hevc.mp4 (Safari/iOS)

4. Use in Your Website

<script type="module">
  import 'stacked-alpha-video';
</script>

<stacked-alpha-video>
  <video autoplay muted playsinline loop>
    <source src="video_stacked_av1.mp4" type='video/mp4; codecs=av01.0.08M.08.0.110.01.01.01.1' />
    <source src="video_stacked_hevc.mp4" type='video/mp4; codecs=hvc1.1.6.H120.b0' />
  </video>
</stacked-alpha-video>

Install the web component: npm install stacked-alpha-video


Usage

Basic Conversion

./scripts/convert-alpha-videos.sh input.mov

Output files are created in the same directory as the input.

Custom Output Directory

./scripts/convert-alpha-videos.sh --output-dir ./output input.mov

Quality Settings

# Higher quality (larger files)
./scripts/convert-alpha-videos.sh --av1-crf 35 --hevc-crf 25 input.mov

# Lower quality (smaller files)
./scripts/convert-alpha-videos.sh --av1-crf 50 --hevc-crf 40 input.mov

CRF Guide: Lower = better quality, larger file

  • 25-30 - Excellent (hero animations)
  • 35-45 - Very good (default: 45)
  • 50-55 - Good (backgrounds)

Encoding Speed

# Fast preview (lower quality)
./scripts/convert-alpha-videos.sh --av1-cpu 6 --hevc-preset medium input.mov

# Production (best quality) - default
./scripts/convert-alpha-videos.sh input.mov

Generate Single Format

# AV1 only (smallest, modern browsers)
./scripts/convert-alpha-videos.sh --av1-only input.mov

# HEVC only (Safari compatibility)
./scripts/convert-alpha-videos.sh --hevc-only input.mov

Batch Conversion

# Convert multiple files
./scripts/convert-all-videos.sh video1.mov video2.mov video3.mov

# Convert all MOV files in directory
./scripts/convert-all-videos.sh videos/*.mov

Options Reference

./scripts/convert-alpha-videos.sh [OPTIONS] INPUT_FILE
Option Default Description
--av1-crf VALUE 45 AV1 quality (0-63, lower=better)
--av1-cpu VALUE 3 AV1 speed (0-8, lower=slower/better)
--hevc-crf VALUE 30 HEVC quality (0-63, lower=better)
--hevc-preset VALUE veryslow HEVC preset (medium/slow/slower/veryslow)
--av1-only - Only generate AV1 version
--hevc-only - Only generate HEVC version
--output-dir DIR same as input Output directory
-h, --help - Show help message

Web Integration

Option 1: Web Component (Recommended)

Install Jake Archibald's web component:

npm install stacked-alpha-video

Use in your JavaScript/React/Vue:

import 'stacked-alpha-video';
<stacked-alpha-video>
  <video autoplay crossorigin="anonymous" muted playsinline loop>
    <source src="video_stacked_av1.mp4" type='video/mp4; codecs=av01.0.08M.08.0.110.01.01.01.1' />
    <source src="video_stacked_hevc.mp4" type='video/mp4; codecs=hvc1.1.6.H120.b0' />
  </video>
</stacked-alpha-video>

Option 2: React Component

import { useEffect, useRef } from 'react';
import 'stacked-alpha-video';

export function TransparentVideo({ src }: { src: string }) {
  return (
    <stacked-alpha-video>
      <video autoPlay muted playsInline loop>
        <source src={`${src}_stacked_av1.mp4`} type='video/mp4; codecs=av01.0.08M.08.0.110.01.01.01.1' />
        <source src={`${src}_stacked_hevc.mp4`} type='video/mp4; codecs=hvc1.1.6.H120.b0' />
      </video>
    </stacked-alpha-video>
  );
}

Option 3: CDN (No Build Step)

<script type="module">
  import 'https://unpkg.com/stacked-alpha-video@1.0.10';
</script>

<stacked-alpha-video>
  <video autoplay muted playsinline loop>
    <source src="video_stacked_av1.mp4" type='video/mp4; codecs=av01.0.08M.08.0.110.01.01.01.1' />
    <source src="video_stacked_hevc.mp4" type='video/mp4; codecs=hvc1.1.6.H120.b0' />
  </video>
</stacked-alpha-video>

Testing the example locally:

See examples/basic-usage.html for a complete example.

# Serve via HTTP (required for WebGL/CORS)
python3 -m http.server 8000 --directory examples
# Then open http://localhost:8000/basic-usage.html

Note: The example won't work when opened directly via file:// protocol due to browser CORS restrictions. You must serve it via HTTP.


Browser Support

Browser AV1 HEVC Recommended
Chrome 90+ AV1
Firefox 93+ AV1
Safari 17+ Both
Safari 11-16 HEVC only
Edge 90+ AV1
iOS 17+ Both
iOS 11-16 HEVC only

Always generate both formats for maximum compatibility.


Input Formats

The converter accepts any video format with an alpha channel:

Recommended:

  • QuickTime Animation codec (.mov)
  • ProRes 4444 (.mov)
  • PNG sequence (converted to video first)

Also works:

  • WebM with VP9 alpha (.webm)
  • Other QuickTime formats with alpha
  • Any FFmpeg-supported format with alpha

See EXPORTING.md for export instructions from various tools.


How It Works

The Problem with Native Alpha

When you try to use transparent videos on the web, you hit these issues:

  • VP9 with alpha - Safari doesn't support it
  • HEVC with alpha - Firefox doesn't support it, files are massive
  • AVIF sequences - Terrible performance, buggy on Safari
  • GIF/WebP - Limited colors, huge file sizes

No single format works everywhere. Until now.

The Stacked Alpha Method

Instead of native alpha channels, Jake Archibald's method splits each frame:

  1. Split - Frames divided into two parts stacked vertically:

    • Top half: RGB color data
    • Bottom half: Alpha data (as brightness)
  2. Encode - Both parts encoded as a standard video (no alpha channel needed)

  3. Composite - A WebGL shader splits and recombines them in real-time in the browser

Result: Works everywhere, 60-85% smaller files, hardware-accelerated playback.

Why This Works Better

Approach Chrome Firefox Safari/iOS File Size Complexity
VP9 with alpha Large Medium
HEVC with alpha Very large High
Stacked alpha 60-85% smaller Simple

Credit: This method was pioneered by Jake Archibald. This tool just makes it easier to use.


Troubleshooting

Video looks corrupted or has no transparency

Cause: Input video doesn't have an alpha channel

Solution:

  1. Re-export with alpha channel enabled (RGBA color mode)
  2. Try QuickTime Animation codec or ProRes 4444
  3. Verify your source has transparency before conversion

Files are too large

Solutions:

# Increase CRF (lower quality, smaller size)
./scripts/convert-alpha-videos.sh --av1-crf 50 --hevc-crf 40 input.mov

# Generate AV1 only (50-60% smaller than HEVC)
./scripts/convert-alpha-videos.sh --av1-only input.mov

# Reduce input resolution in your video editor

Encoding is very slow

Normal: AV1 encoding is CPU-intensive (10-30 min for a 10s video)

Speed up preview encoding:

./scripts/convert-alpha-videos.sh --av1-cpu 6 --hevc-preset medium input.mov

"ffmpeg: command not found"

Solution: Install FFmpeg:

# macOS
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

# Windows
choco install ffmpeg

Alpha not working in browser

Check:

  1. Using the stacked-alpha-video web component?
  2. Browser supports WebGL?
  3. Check browser console for errors
  4. Verify source video has transparency

File Size Examples

Real-world compression results:

Video Duration Native VP9 Stacked AV1 Stacked HEVC Savings
UI Animation 5s 2.1 MB 287 KB 412 KB 86%
Logo Reveal 3s 1.8 MB 201 KB 356 KB 89%
Product Demo 10s 3.7 MB 428 KB 661 KB 88%

Results vary based on content complexity and settings


Resources


Contributing

Contributions welcome! This tool is designed to be:

  • Simple - Bash scripts, minimal dependencies
  • Portable - macOS, Linux, Windows (with bash)
  • Extensible - Easy to modify for your needs

License

MIT License - See LICENSE for details.


Support

For issues or questions, please open an issue on GitHub.

Happy encoding! 🎥✨

About

Convert videos with alpha channels into highly optimized web-ready formats. This tool implements Jake Archibald's stacked alpha method, achieving 60-85% smaller file sizes than native transparency formats while maintaining perfect cross-browser compatibility.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages