You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Personal media server with a robust Node.js backend and an ultra-light Netflix-like web client. The server handles all heavy lifting — transcoding, metadata, library scanning — while the client is a thin Preact shell that streams HLS adaptive video.
Features
Adaptive bitrate streaming — On-the-fly HLS transcoding via FFmpeg (1080p/720p/480p/360p)
Direct play — Zero-transcode for browser-compatible formats (H.264 MP4, WebM, etc.)
Algorithmic recommendations — 5-strategy engine (next episode, collaborative filtering, genre matching, similar items, popularity) with no external AI APIs
User preferences — Like/dislike with recommendation cache invalidation
Library health dashboard — 8 checks (missing files, zero-byte, metadata gaps, no subtitles, codec/resolution analysis, orphaned entries, duplicates) with admin cleanup
Ultra-light client — Preact + HTM loaded from CDN (~3KB framework), no build step
Dark Netflix-like UI — Responsive grid layout with category browsing, search, ARIA labels
Requirements
Node.js >= 22
FFmpeg + FFprobe installed and available in $PATH
Quick Start
# Clone and install
git clone https://github.com/kosm1x/vlmp.git
cd vlmp
npm install
# Start in development mode (auto-reload)
npm run dev
# Open http://localhost:8080# Register the first user (automatically becomes admin)
Configuration
All configuration is via environment variables:
Variable
Default
Description
VLMP_PORT
8080
HTTP server port
VLMP_HOST
0.0.0.0
Bind address
VLMP_DATA_DIR
./data
Data directory (database, transcode cache)
VLMP_JWT_SECRET
vlmp-dev-secret-change-me
JWT signing secret (change in production)
VLMP_JWT_EXPIRES_IN
24h
JWT token lifetime
VLMP_FFMPEG_PATH
ffmpeg
Path to FFmpeg binary
VLMP_FFPROBE_PATH
ffprobe
Path to FFprobe binary
VLMP_TMDB_API_KEY
(empty)
TMDb API key for metadata enrichment
VLMP_SERVER_NAME
VLMP
Display name for this server in federation
VLMP_PUBLIC_URL
(empty)
Public URL of this server (for federation linking)
Two VLMP instances can link up so users on Server A can browse and play media from Server B, all proxied through Server A (NAT-safe — the client never talks directly to remote servers).
How to Link Servers
Server B admin goes to Servers page and clicks "Generate Invite Token"
Server A admin enters Server B's URL + invite token in the "Link to Server" form
Both servers now show as active — Server A's users can browse and play Server B's library
Architecture
HMAC-SHA256 auth — Every cross-server request signed with 3 headers (X-VLMP-Server-Id, X-VLMP-Timestamp, X-VLMP-Signature), with 300s replay window
Proxy pattern — All federation traffic proxied through local server; HLS playlist URLs rewritten to local proxy paths
Sensitive field stripping — file_path, file_size, library_folder_id removed from all remote responses
Health monitoring — 5-minute heartbeat loop; server marked offline after 3 consecutive failures, auto-recovers on next success
Config — Set VLMP_SERVER_NAME and VLMP_PUBLIC_URL env vars for federation
Direct play (no transcode) requires: H.264/VP8/VP9/AV1 video + AAC/MP3/Opus/Vorbis/FLAC audio in MP4/WebM/M4V containers. Everything else is transcoded to HLS on-the-fly.
Media Organization
VLMP classifies media by folder category. When adding a library folder, assign a category:
Category
What it expects
movies
Title (Year).ext or any standalone video
tv
Files with S01E01, 1x01 patterns; folders like Season 1/
documentaries
Single documentary files
doc_series
Documentary series with episode patterns
education
Numbered lessons (e.g., 01 - Introduction.mp4)
other
Anything else
Database
SQLite with WAL journal mode for concurrent read/write. Tables include: