video_press/README.md

145 lines
4.2 KiB
Markdown
Raw Normal View History

2026-03-09 17:42:26 -05:00
# VideoPress — FFmpeg Video Compressor
2026-03-09 17:54:34 -05:00
NOTE: This application was built with the help of AI.
- [x] The application code has been reviewed by this developer.
- [x] The application code has been tested by this developer.
If you find any issues, please feel free to post an issue, and / or a pull request for a fix.
## What is VideoPress?
2026-03-09 17:42:26 -05:00
A web-based video compression tool served via **Gunicorn + gevent** (WSGI),
containerised with **Docker**. FFmpeg compresses video files to approximately
1/3 their original size. All file-system access is restricted to a single
configurable media root for security.
---
## Quick start with Docker (recommended)
Step. 1. You have two options
2026-03-12 16:53:21 -05:00
A. Build the image
2026-03-12 16:53:21 -05:00
2026-03-12 16:54:21 -05:00
`docker build -t videopress .`
B. Use the pre-built image
2026-03-12 16:53:21 -05:00
2026-03-12 16:54:21 -05:00
Already included in the `docker-compose.yml` file witht his project.
Step 2. Run — replace `/your/video/path` with the real path on your host
2026-03-12 16:53:21 -05:00
A. Using `docker run`:
2026-03-12 16:55:53 -05:00
```
docker run -d \
2026-03-09 17:42:26 -05:00
--name videopress \
--restart unless-stopped \
-p 8080:8080 \
-v /your/video/path:/media \
videopress
```
B. Using Docker Compose
2026-03-12 16:53:21 -05:00
`docker compose up -d`
2026-03-09 17:42:26 -05:00
Step 3. Open http://localhost:8080
2026-03-09 17:42:26 -05:00
---
## Bare-metal (without Docker)
### Requirements
| Tool | Version |
|------|---------|
| Python | 3.8+ |
| FFmpeg + FFprobe | any recent |
| pip packages | see requirements.txt |
```bash
2026-03-09 17:54:34 -05:00
# Create a python virtual environment to run in
python3 -m venv videopress
#start the virtual environment
source ./videopress/bin/activate
2026-03-09 17:42:26 -05:00
# Install Python dependencies
pip install -r requirements.txt
# Development server (Flask built-in — not for production)
./start.sh
# Production server (Gunicorn + gevent)
MEDIA_ROOT=/your/video/path ./start.sh --prod
# or on a custom port:
MEDIA_ROOT=/your/video/path ./start.sh --prod 9000
```
---
## Security model
Every API call that accepts a path validates it with `safe_path()` before any
OS operation. `safe_path()` resolves symlinks and asserts the result is inside
`MEDIA_ROOT`. Requests that attempt directory traversal are rejected with
HTTP 403. The container runs as a non-root user (UID 1000).
---
## Architecture
```
Browser ──HTTP──▶ Gunicorn (gevent worker)
├─ GET / → index.html
├─ GET /api/config → {"media_root": ...}
├─ GET /api/browse → directory listing
├─ POST /api/scan → ffprobe metadata
├─ POST /api/compress/start → launch ffmpeg thread
├─ GET /api/compress/progress/<id> ← SSE stream
└─ POST /api/compress/cancel/<id>
```
**Why gevent?** SSE (`/api/compress/progress`) is a long-lived streaming
response. Standard Gunicorn sync workers block for its entire duration.
Gevent workers use cooperative greenlets so a single worker process can
handle many concurrent SSE streams and normal requests simultaneously.
**Why workers=1?** Job state lives in an in-process Python dict. Multiple
worker *processes* would not share it. One gevent worker with many greenlets
is sufficient for this workload. To scale to multiple workers, replace the
in-process job store with Redis.
---
## Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| `MEDIA_ROOT` | `/media` | Root directory the app may access |
| `PORT` | `8080` | Port Gunicorn listens on |
| `LOG_LEVEL` | `info` | Gunicorn log level |
---
## File layout
```
videocompressor/
├── app.py ← Flask application + all API routes
├── wsgi.py ← Gunicorn entry point (imports app from app.py)
├── gunicorn.conf.py ← Gunicorn configuration (gevent, timeout, logging)
├── requirements.txt ← Python dependencies
├── Dockerfile ← Two-stage Docker build
├── docker-compose.yml ← Volume mapping, port, env vars
├── start.sh ← Helper script (dev + prod modes)
├── README.md
├── templates/
│ └── index.html
└── static/
├── css/main.css
└── js/app.js
```