Initial Commit
This commit is contained in:
commit
e2f743e8bc
11 changed files with 3104 additions and 0 deletions
125
README.md
Normal file
125
README.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# VideoPress — FFmpeg Video Compressor
|
||||
|
||||
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)
|
||||
|
||||
```bash
|
||||
# 1. Build the image
|
||||
docker build -t videopress .
|
||||
|
||||
# 2. Run — replace /your/video/path with the real path on your host
|
||||
docker run -d \
|
||||
--name videopress \
|
||||
--restart unless-stopped \
|
||||
-p 8080:8080 \
|
||||
-v /your/video/path:/media \
|
||||
videopress
|
||||
|
||||
# 3. Open http://localhost:8080
|
||||
```
|
||||
|
||||
### With docker compose
|
||||
|
||||
```bash
|
||||
# Edit the volume path in docker-compose.yml (or export the env var):
|
||||
export MEDIA_HOST_PATH=/your/video/path
|
||||
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bare-metal (without Docker)
|
||||
|
||||
### Requirements
|
||||
|
||||
| Tool | Version |
|
||||
|------|---------|
|
||||
| Python | 3.8+ |
|
||||
| FFmpeg + FFprobe | any recent |
|
||||
| pip packages | see requirements.txt |
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue