README.md
Rama dev · réplica de lectura del repositorio original.
# VLog - Self-Hosted Video Platform
> **Note:** This project was built almost entirely with AI assistance (Claude Code). It's a "vibe-coded" project - functional and useful, but built through AI pair-programming rather than traditional development. Use accordingly, and contributions are welcome!
A lightweight, self-hosted video platform with 4K support, HLS adaptive streaming, auto-transcription, and a clean modern UI.
## Features
### Video Processing
- **4K Video Support** - Transcode to 2160p, 1440p, 1080p, 720p, 480p, 360p (YouTube-style quality ladder)
- **HLS + DASH Streaming** - Adaptive bitrate with both HLS and DASH (CMAF/fMP4) support
- **Modern Codecs** - H.264, HEVC (H.265), and AV1 encoding with GPU acceleration
- **Distributed Transcoding** - Containerized workers in Kubernetes with automatic job distribution
- **Re-encode Queue** - Batch convert legacy videos to modern CMAF format with HEVC/AV1
- **Auto-Transcription** - Automatic subtitles using faster-whisper (WebVTT captions)
- **Event-Driven Processing** - Instant video detection via inotify (no polling delay)
- **Crash Recovery** - Checkpoint-based resumable transcoding
### Content Management
- **Playlists & Collections** - Organize videos into playlists, collections, series, or courses
- **Video Chapters** - Timeline navigation with chapter markers (up to 50 per video)
- **Sprite Sheet Previews** - Thumbnail previews for timeline scrubbing
- **Featured Videos** - Mark videos as featured for homepage prominence
- **Custom Metadata Fields** - Define custom fields per category (text, number, date, select, URL)
- **Custom Thumbnails** - Select from video frames or upload custom images
- **Soft-Delete** - Deleted videos go to archive with configurable retention period
- **YouTube Migration** - Download and import videos directly from YouTube
### Streaming & Delivery
- **CDN Support** - Configure external CDN for video delivery
- **Shaka Player + hls.js** - Dual player support for DASH and HLS formats
- **Client-Side Watermarks** - Configurable image or text overlays on playback
### Admin & Operations
- **Modern Admin UI** - TypeScript-based admin interface with mobile support
- **Display Settings** - Configurable public UI (view counts, tagline)
- **Prometheus Metrics** - Full observability with `/metrics` endpoints
- **Automated Backups** - Kubernetes CronJob for PostgreSQL backups
- **Audit Logging** - Security event logging with rotation
- **Database-Backed Settings** - Runtime configuration via Admin UI or CLI
- **CLI + Web Upload** - Upload via command line or web interface
### Reliability
- **Circuit Breaker** - Worker HTTP client resilience pattern
- **Streaming Segment Upload** - Progressive upload during transcoding (optional)
- **Worker Version Gating** - Prevent stale workers from processing jobs
- **Table Partitioning** - Analytics table partitioned by month for performance
### Security & Infrastructure
- **Admin Authentication** - Secure admin API with API keys and HTTP-only cookie sessions
- **Rate Limiting** - Configurable per-endpoint rate limits (memory or Redis storage)
- **Playback Analytics** - Track views, watch time, completion rates
- **Kubernetes Security** - NetworkPolicy, PodDisruptionBudgets, seccomp profiles
## Requirements
- **Python 3.12+**
- **ffmpeg** with libx264 and aac support
- **yt-dlp** (optional, for YouTube downloads)
- **faster-whisper** (optional, for auto-transcription)
## Quick Start
```bash
# Clone and setup
git clone https://github.com/filthyrake/vlog.git
cd vlog
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install package in development mode
pip install -e .
# Initialize database
python api/database.py
# Start all services
./start.sh
```
Access:
- **Public Site:** http://localhost:9000
- **Admin Panel:** http://localhost:9001
## Services
| Service | Port | Description |
|---------|------|-------------|
| Public API | 9000 | Video browsing and HLS playback |
| Admin API | 9001 | Upload and management (internal only) |
| Worker API | 9002 | Remote worker registration and job distribution |
| Transcoding Worker | - | Local event-driven video processing |
| Remote Workers | - | Containerized transcoding in Kubernetes |
| Transcription Worker | - | Auto-captioning (faster-whisper) |
## CLI Usage
```bash
# The package installs a 'vlog' command automatically
# Make sure your venv is activated
# Upload a video
vlog upload video.mp4 -t "My Video Title" -c "Category Name"
# List videos
vlog list
vlog list -s processing # Filter by status
# Manage categories
vlog categories # List all
vlog categories --create "Tutorials" # Create new
# Download from YouTube
vlog download "https://youtube.com/watch?v=..." -c "Category"
# Delete a video
vlog delete 123
# Worker management (for distributed transcoding)
vlog worker register --name "k8s-worker-1" # Get API key for new worker
vlog worker status # Show all workers and current jobs
vlog worker list # List registered workers
# Settings management (runtime configuration)
vlog settings list # List all settings
vlog settings get transcoding.hls_segment_duration # Get a setting
vlog settings set transcoding.hls_segment_duration 10 # Update a setting
vlog settings migrate-from-env # Migrate env vars to database
# Manifest management (for CMAF videos)
vlog manifests regenerate --all # Regenerate all CMAF manifests
vlog manifests regenerate --slug my-video # Regenerate specific video
```
## Directory Structure
```
vlog/
├── pyproject.toml # Package configuration
├── api/ # FastAPI backend
│ ├── public.py # Public API (port 9000)
│ ├── admin.py # Admin API (port 9001)
│ ├── worker_api.py # Worker API (port 9002)
│ ├── worker_auth.py # API key authentication
│ ├── database.py # SQLAlchemy schema
│ └── schemas.py # Pydantic models
├── worker/
│ ├── transcoder.py # Local HLS transcoding worker
│ ├── remote_transcoder.py # Containerized remote worker
│ ├── hwaccel.py # GPU detection and hardware encoder selection
│ ├── http_client.py # Worker API client
│ └── transcription.py # Whisper transcription worker
├── web/
│ ├── public/ # Public-facing frontend
│ └── admin/ # Admin interface
├── cli/
│ └── main.py # Command-line tool (upload, worker mgmt)
├── k8s/ # Kubernetes manifests for workers
├── systemd/ # Systemd service files
├── docs/ # Documentation
├── Dockerfile.worker # Container image for CPU-only workers
├── Dockerfile.worker.gpu # GPU-enabled container (Rocky Linux 10, NVENC/VAAPI)
├── config.py # Central configuration (env var support)
├── vlog.db # SQLite database (local)
└── start.sh # Development startup script
```
## Storage Layout
```
/mnt/nas/vlog-storage/
├── uploads/ # Temporary upload storage
│ └── {video_id}.mp4
├── videos/ # Transcoded output
│ └── {slug}/
│ ├── master.m3u8 # HLS adaptive bitrate playlist
│ ├── manifest.mpd # DASH manifest (CMAF format)
│ ├── 1080p/ # CMAF quality (fMP4 segments)
│ │ ├── init.mp4 # Initialization segment
│ │ ├── segment_0.m4s # Media segments
│ │ └── ...
│ ├── 1080p.m3u8 # Legacy HLS quality playlist
│ ├── 1080p_0000.ts # Legacy HLS segments (MPEG-TS)
│ ├── thumbnail.jpg
│ ├── captions.vtt # WebVTT subtitles
│ └── sprites/ # Timeline preview sprites
│ ├── sprite_0.jpg
│ └── ...
├── archive/ # Soft-deleted videos
│ └── {slug}/
└── backups/ # PostgreSQL database backups
└── vlog-YYYY-MM-DD.dump
```
**Streaming Formats:**
- **CMAF (new):** Modern fMP4 segments with both HLS and DASH manifests. Uses Shaka Player.
- **HLS/TS (legacy):** Traditional MPEG-TS segments with HLS only. Uses hls.js.
## Quality Presets
Videos are transcoded to all resolutions at or below the source:
| Quality | Bitrate | Audio |
|---------|---------|-------|
| 2160p (4K) | 15 Mbps | 192 kbps |
| 1440p | 8 Mbps | 192 kbps |
| 1080p | 5 Mbps | 128 kbps |
| 720p | 2.5 Mbps | 128 kbps |
| 480p | 1 Mbps | 96 kbps |
| 360p | 600 kbps | 96 kbps |
## Production Deployment
For production, use systemd to manage services:
```bash
# Enable and start all services
sudo systemctl enable vlog.target
sudo systemctl start vlog.target
# Check status
sudo systemctl status vlog-public vlog-admin vlog-worker
# View logs
sudo journalctl -u vlog-worker -f
```
See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for full production setup including nginx configuration.
### Distributed Transcoding (Kubernetes)
For horizontal scaling, deploy containerized workers to Kubernetes:
```bash
# Register workers and get API keys
vlog worker register --name "k8s-worker-1"
# Save the returned API key
# Deploy to k8s
kubectl apply -f k8s/namespace.yaml
kubectl create secret generic vlog-worker-secret -n vlog \
--from-literal=api-key='YOUR_API_KEY'
kubectl apply -f k8s/
# Check worker status
vlog worker status
kubectl logs -n vlog -l app=vlog-worker -f
```
See [k8s/README.md](k8s/README.md) for detailed Kubernetes deployment instructions.
## Documentation
| Document | Description |
|----------|-------------|
| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | System architecture and data flows |
| [API.md](docs/API.md) | Complete API reference |
| [DATABASE.md](docs/DATABASE.md) | Database schema documentation |
| [CONFIGURATION.md](docs/CONFIGURATION.md) | Configuration options |
| [DEPLOYMENT.md](docs/DEPLOYMENT.md) | Production deployment guide |
| [MONITORING.md](docs/MONITORING.md) | Prometheus metrics and observability |
| [ADMIN_UI_GUIDE.md](docs/ADMIN_UI_GUIDE.md) | Admin interface user guide |
| [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | Common issues and solutions |
| [UPGRADING.md](docs/UPGRADING.md) | Version upgrade procedures |
| [TRANSCODING_ARCHITECTURE.md](docs/TRANSCODING_ARCHITECTURE.md) | Job lifecycle and state machine |
| [EXCEPTION_HANDLING.md](docs/EXCEPTION_HANDLING.md) | Error handling patterns |
## Configuration
All settings can be configured via environment variables (prefix: `VLOG_`) or by editing `config.py`:
```bash
# Storage paths
VLOG_STORAGE_PATH=/mnt/nas/vlog-storage
# Server ports
VLOG_PUBLIC_PORT=9000
VLOG_ADMIN_PORT=9001
# Transcription
VLOG_WHISPER_MODEL=medium # tiny, base, small, medium, large-v3
VLOG_TRANSCRIPTION_ENABLED=true
# Rate limiting
VLOG_RATE_LIMIT_ENABLED=true
VLOG_RATE_LIMIT_PUBLIC_DEFAULT=100/minute
VLOG_RATE_LIMIT_STORAGE_URL=memory:// # or redis://localhost:6379
# Soft-delete retention
VLOG_ARCHIVE_RETENTION_DAYS=30
# Local worker mode
VLOG_WORKER_USE_FILESYSTEM_WATCHER=true # inotify vs polling
# Remote workers (Kubernetes)
VLOG_WORKER_API_PORT=9002
VLOG_WORKER_API_URL=http://your-server:9002
VLOG_WORKER_API_KEY=your-api-key
```
See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for all options.
### Authentication
VLog uses multi-user authentication with role-based access control (RBAC). On first access, a setup wizard guides you through creating the initial admin account.
```bash
# Required: Set a session secret for signing tokens
# Generate with: openssl rand -base64 32
export VLOG_SESSION_SECRET_KEY=your-secret-key-here
```
**Features:**
- Session-based auth with JWT refresh tokens
- Role-based access control (admin, editor, viewer)
- API keys for programmatic access
- OIDC integration (Google, GitHub, Keycloak, etc.)
- Invite-based user registration
See [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) for full details.
<details>
<summary>Legacy Authentication (deprecated)</summary>
The legacy single-secret authentication via `VLOG_ADMIN_API_SECRET` is still supported as a fallback but is deprecated. Migrate to multi-user auth for better security and audit logging.
</details>
## Troubleshooting
### Video stuck in "processing"
```bash
# Check worker logs
sudo journalctl -u vlog-worker -f
# Common causes:
# - ffmpeg not installed or missing codecs
# - Disk space full
# - NAS mount issues
```
### Upload fails
```bash
# Check admin logs
sudo journalctl -u vlog-admin -f
# Common causes:
# - uploads/ directory not writable
# - File too large (check nginx client_max_body_size)
```
### Playback issues
1. Verify HLS files exist: `ls /mnt/nas/vlog-storage/videos/{slug}/`
2. Check MIME types in browser dev tools (`.ts` should be `video/mp2t`)
3. Check CORS headers if using different domains
### Transcription not working
```bash
# Check transcription worker
sudo journalctl -u vlog-transcription -f
# Verify faster-whisper is installed
pip show faster-whisper
```
## Testing
VLog has comprehensive test coverage with unit, integration, and end-to-end tests.
```bash
# Install test dependencies
pip install pytest pytest-asyncio pytest-cov
# Run all tests with coverage
VLOG_TEST_MODE=1 pytest
# Run specific test types
VLOG_TEST_MODE=1 pytest -m integration # Integration tests only
VLOG_TEST_MODE=1 pytest -m e2e # End-to-end tests only
# Generate coverage report
VLOG_TEST_MODE=1 pytest --cov=api --cov=worker --cov=cli --cov-report=html
open htmlcov/index.html # View coverage report
```
**Requirements:**
- PostgreSQL server (tests create temporary databases)
- Test environment variables (see `TESTING.md`)
**Test Coverage:**
- 37+ test files with 900+ test cases
- Unit tests for all major components
- Integration tests for workflows
- End-to-end tests for complete flows
- Database migration tests
See [TESTING.md](TESTING.md) for detailed testing guide.
## Tech Stack
- **Backend:** FastAPI + Uvicorn
- **Database:** PostgreSQL + SQLAlchemy (async via asyncpg)
- **Video Processing:** FFmpeg 7.1.2 (NVENC, VAAPI, QSV hardware encoding)
- **Transcription:** faster-whisper
- **File Monitoring:** watchdog (inotify)
- **Rate Limiting:** slowapi (memory or Redis)
- **Metrics:** prometheus-client (Prometheus text format)
- **Frontend:** Alpine.js + Tailwind CSS v4, TypeScript (Admin UI)
- **Video Player:** Shaka Player (DASH/CMAF), hls.js (HLS/TS legacy)
- **Process Management:** systemd
- **Container Orchestration:** Kubernetes (k3s)
## License
MIT License - See LICENSE file for details.