Local video compression powered by WebCodecs — hardware-accelerated, zero FFmpeg required
Project description
VidCompress
Local, hardware-accelerated video compression that runs entirely in your browser — or natively on your iPhone. No FFmpeg install, no cloud uploads.
curl -LsSf https://astral.sh/uv/install.sh | sh
uvx vidcompress
How it works
VidCompress launches a tiny local web server and opens a browser tab. All video encoding/decoding happens client-side using the WebCodecs API, which talks directly to your GPU's hardware encoder (VideoToolbox on Mac, NVENC on NVIDIA, AMF on AMD).
┌──────────────────────────────────────────────────────────┐
│ Browser (Chrome/Edge) │
│ │
│ MP4Box.js VideoDecoder VideoEncoder mp4-muxer │
│ (demux) → (HW decode) → (HW encode) → (remux) │
│ │
│ ↕ GPU: VideoToolbox / NVENC / AMF / VA-API │
└──────────────────────────────────────────────────────────┘
│ Python server (FastAPI) — only serves static files │
└──────────────────────────────────────────────────────────┘
Your files never leave your machine.
Quick start
With uv (recommended)
# Run directly — no install needed
uvx vidcompress
# Or install globally
uv tool install vidcompress
vidcompress
With pip
pip install vidcompress
vidcompress
From source
git clone https://github.com/arpantripathi/ffmpeg-compression-local.git
cd ffmpeg-compression-local
uv run vidcompress
Features
- Hardware-accelerated — uses your GPU encoder, not software encoding
- Zero dependencies — no FFmpeg, no native libraries to install
- Fully local — nothing leaves your machine
- Codec choice — H.264, H.265 (HEVC), VP9, AV1
- Resolution scaling — downscale to 1080p, 720p, 480p, 360p
- Quality control — adjustable quality slider with exponential bitrate mapping
- Audio re-encoding — automatic AAC/Opus transcoding
- Drag & drop — simple, clean UI
Supported codecs
| Codec | Container | Mac (Apple Silicon) | Windows (NVIDIA) | Windows (AMD) |
|---|---|---|---|---|
| H.264 (AVC) | MP4 | VideoToolbox | NVENC | AMF |
| H.265 (HEVC) | MP4 | VideoToolbox | NVENC | AMF |
| VP9 | WebM | Software* | Software* | Software* |
| AV1 | MP4 | VideoToolbox (M3+) | NVENC (RTX 40+) | AMF (RX 7000+) |
*VP9 encoding may fall back to software on some platforms. Hardware support depends on your browser and GPU drivers.
Performance
Typical encoding speeds for 1080p video (hardware-accelerated):
| Codec | Apple M1/M2 | NVIDIA RTX 3060+ | AMD RX 6000+ |
|---|---|---|---|
| H.264 | 200-400 fps | 300-500 fps | 200-350 fps |
| H.265 | 150-300 fps | 200-400 fps | 150-250 fps |
| AV1 | 60-120 fps (M2+) | 100-200 fps (RTX 40+) | 80-150 fps |
A 10-minute 1080p video typically compresses in 30-90 seconds.
Browser requirements
- Chrome 94+ or Edge 94+ (full WebCodecs support)
- Firefox: partial support (video encoding may not work)
- Safari: partial support (limited codec options)
CLI options
vidcompress [OPTIONS]
Options:
-p, --port PORT Port to serve on (default: 8899)
--host HOST Host to bind to (default: 127.0.0.1)
--no-open Don't open browser automatically
--version Show version and exit
-h, --help Show help
Development
git clone https://github.com/arpantripathi/ffmpeg-compression-local.git
cd ffmpeg-compression-local
# Run in development
uv run vidcompress
# Or with live reload (edit static files, refresh browser)
uv run vidcompress --port 3000
The Python server is minimal — it only serves static files. All encoding logic is in src/vidcompress/static/app.js.
Architecture
src/vidcompress/
├── __init__.py # Version
├── __main__.py # python -m vidcompress
├── cli.py # CLI argument parsing + server launch
├── server.py # FastAPI static file server (10 lines)
└── static/
├── index.html # UI structure
├── style.css # Dark theme
└── app.js # WebCodecs transcoding pipeline
Frontend pipeline (app.js)
- Demux — mp4box.js reads the input MP4/MOV and extracts raw encoded samples
- Decode —
VideoDecoder(hardware) decodes samples into rawVideoFrames - Resize —
OffscreenCanvasscales frames if resolution change is requested - Encode —
VideoEncoder(hardware) re-encodes frames with the chosen codec/bitrate - Mux — mp4-muxer or webm-muxer packages encoded chunks into the output container
- Download — output is offered as a browser download
iOS App
VidCompress is also available as a native iOS app, with the same hardware-accelerated compression pipeline running directly on your iPhone.
Requirements
- iPhone with iOS 16.0+
- Xcode 15+ on your Mac (to build and install)
Build & install
git clone https://github.com/arpantripathi/ffmpeg-compression-local.git
cd ffmpeg-compression-local/ios/VidCompress
# Open in Xcode
open VidCompress.xcodeproj
- In Xcode, select your Apple ID team under Signing & Capabilities
- Change the Bundle Identifier to something unique (e.g.
com.yourname.vidcompress) - Connect your iPhone via USB, select it as the run destination
- Press Cmd+R to build and install
Features
- Same compression engine — AVFoundation with VideoToolbox hardware encoding
- Same bitrate formula — identical quality mapping as the web version
- Codec support — H.264, H.265 (HEVC), AV1 (A17 Pro+ only)
- Resolution scaling — Original, 2160p, 1440p, 1080p, 720p, 480p
- Audio — AAC re-encoding at 128kbps
- Comparison slider — side-by-side original vs compressed with synced playback
- Share sheet — export compressed video directly from the app
- Zero dependencies — pure Apple frameworks, no third-party libraries
Supported codecs (iOS)
| Codec | Availability |
|---|---|
| H.264 (AVC) | All iOS 16+ devices |
| H.265 (HEVC) | All iOS 16+ devices (A10+) |
| AV1 | iPhone 15 Pro+ (A17 Pro / M3+) |
Architecture (iOS)
ios/VidCompress/VidCompress/
├── VidCompressApp.swift # App entry point
├── Models/
│ ├── Codec.swift # H.264, H.265, AV1 definitions
│ ├── Resolution.swift # Resolution options + scaling logic
│ ├── CompressionSettings.swift # Quality, resolution, codec selection
│ ├── VideoMetadata.swift # Input file metadata
│ └── CompressionResult.swift # Output stats
├── Services/
│ ├── VideoCompressor.swift # AVAssetReader → AVAssetWriter pipeline
│ ├── CodecAvailability.swift # Runtime codec detection
│ └── VideoMetadataExtractor.swift # Probe input file
├── ViewModels/
│ └── CompressorViewModel.swift # State machine + orchestration
├── Views/
│ ├── ContentView.swift # Root view
│ ├── VideoPickerView.swift # PHPicker wrapper
│ ├── InputPreviewView.swift # Video player + file info
│ ├── SettingsView.swift # Codec, resolution, quality controls
│ ├── CompressionProgressView.swift # Progress bar
│ ├── ComparisonView.swift # Dual-video comparison slider
│ ├── ResultView.swift # Stats + share button
│ └── PlayerLayerView.swift # AVPlayerLayer wrapper
└── Utilities/
├── BitrateCalculator.swift # Bitrate formula (same as web)
└── FormatHelpers.swift # Byte/duration formatting
iOS compression pipeline
┌────────────────────────────────────────────────────┐
│ AVAssetReader AVAssetWriter │
│ │
│ TrackOutput → WriterInput (video) │
│ (HW decode) (HW encode via VideoToolbox) │
│ │
│ TrackOutput → WriterInput (audio) │
│ (decompress) (AAC 128kbps) │
└────────────────────────────────────────────────────┘
Limitations
- Input formats: MP4 and MOV files only (mp4box.js limitation). WebM input is not supported yet.
- File size: Limited by browser memory. Files over ~2 GB may cause issues.
- Codec availability: Depends on your browser, OS, and GPU. H.265 and AV1 encoding may not be available on all systems.
- No B-frame control: WebCodecs doesn't expose fine-grained encoding parameters like CRF or B-frame count.
- Audio: Audio re-encoding may fail for some input formats. The video will still be compressed.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vidcompress-0.1.4.tar.gz.
File metadata
- Download URL: vidcompress-0.1.4.tar.gz
- Upload date:
- Size: 2.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b98869f01a03edaa150364fb5316dfcdc63c0750b92cf6b0bdf7e3ce92489a4b
|
|
| MD5 |
938e9ca775f2d977190cfbd00e43685c
|
|
| BLAKE2b-256 |
f9dba1b6e17a9b59945dda13ca44ecfab4614f401d443382939256b3cd0468f1
|
File details
Details for the file vidcompress-0.1.4-py3-none-any.whl.
File metadata
- Download URL: vidcompress-0.1.4-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
906751f1c64c7f409d23bbf8162e9861cc5edb9a6e0c04f76dc99762c639b20d
|
|
| MD5 |
2df2321f855ff7d38b248aa5f025b593
|
|
| BLAKE2b-256 |
f1267a0c3f78a4e0890c72d4fe16e5dd70777e850b48e9c7dfe8191c8f11a768
|