Metadata-Version: 2.4
Name: vidcompress
Version: 0.1.4
Summary: Local video compression powered by WebCodecs — hardware-accelerated, zero FFmpeg required
Project-URL: Homepage, https://github.com/arpantripathi/ffmpeg-compression-local
Project-URL: Repository, https://github.com/arpantripathi/ffmpeg-compression-local
Author: Arpan Tripathi
License-Expression: MIT
License-File: LICENSE
Keywords: compression,local,transcoding,video,webcodecs
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Video :: Conversion
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.100.0
Requires-Dist: uvicorn[standard]>=0.20.0
Description-Content-Type: text/markdown

# VidCompress

![alt text](image.png)
<img src="image-1.png" width="50%" /> 


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](https://developer.mozilla.org/en-US/docs/Web/API/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)

```bash
# Run directly — no install needed
uvx vidcompress

# Or install globally
uv tool install vidcompress
vidcompress
```

### With pip

```bash
pip install vidcompress
vidcompress
```

### From source

```bash
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

```bash
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)

1. **Demux** — mp4box.js reads the input MP4/MOV and extracts raw encoded samples
2. **Decode** — `VideoDecoder` (hardware) decodes samples into raw `VideoFrame`s
3. **Resize** — `OffscreenCanvas` scales frames if resolution change is requested
4. **Encode** — `VideoEncoder` (hardware) re-encodes frames with the chosen codec/bitrate
5. **Mux** — mp4-muxer or webm-muxer packages encoded chunks into the output container
6. **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

```bash
git clone https://github.com/arpantripathi/ffmpeg-compression-local.git
cd ffmpeg-compression-local/ios/VidCompress

# Open in Xcode
open VidCompress.xcodeproj
```

1. In Xcode, select your Apple ID team under **Signing & Capabilities**
2. Change the **Bundle Identifier** to something unique (e.g. `com.yourname.vidcompress`)
3. Connect your iPhone via USB, select it as the run destination
4. 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
