Open Media Server API - Stream movies, music & series with community client support
| backend | ||
| frontend | ||
| docker-compose.yml | ||
| README.md | ||
| TASK.md | ||
🐍 Viper Media Server
Open-source media server API — stream your movies, series and music with any client.
Quick Start (Self-Host)
git clone https://git.radionet.app/Jarvis/viper-media-server
cd viper-media-server
# Edit docker-compose.yml: set your media paths
docker-compose up -d
Server runs at http://localhost:8200
Interactive API docs: http://localhost:8200/docs
Environment Variables
| Variable | Default | Description |
|---|---|---|
MOVIES_PATH |
/media/Movies |
Path to movies folder |
SERIES_PATH |
/media/Series |
Path to series folder |
MUSIC_PATH |
/media/Music |
Path to music folder |
DB_PATH |
./viper.db |
SQLite database path |
PORT |
8200 |
HTTP port |
API_KEY |
(empty) | Optional API key (leave empty to disable auth) |
API Endpoints
🎬 Movies
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/movies |
List movies (?page=1&limit=20&search=batman) |
| GET | /api/v1/movies/{id} |
Movie detail + metadata |
| GET | /api/v1/movies/{id}/similar |
Similar movies by year |
Example response:
{
"id": 1,
"title": "Inception",
"year": 2010,
"duration": 8869.4,
"size": 4831838208,
"codec": "h264",
"resolution": "1080p",
"stream_url": "/api/v1/stream/movie/1",
"thumbnail_url": "/api/v1/stream/thumbnail/movie/1"
}
📺 Series
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/series |
List all series |
| GET | /api/v1/series/{id} |
Series detail + seasons list |
| GET | /api/v1/series/{id}/seasons |
Seasons list |
| GET | /api/v1/series/{id}/seasons/{season}/episodes |
Episodes for a season |
🎵 Music
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/music/artists |
All artists |
| GET | /api/v1/music/artists/{id} |
Artist + albums |
| GET | /api/v1/music/albums |
All albums (?page=1&search=) |
| GET | /api/v1/music/albums/{id} |
Album + tracks |
| GET | /api/v1/music/tracks |
All tracks (paginated) |
| GET | /api/v1/music/tracks/{id} |
Track detail |
▶️ Streaming
All streaming endpoints support HTTP Range Requests for seeking.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/stream/movie/{id} |
Stream movie file |
| GET | /api/v1/stream/episode/{id} |
Stream episode file |
| GET | /api/v1/stream/track/{id} |
Stream audio track |
| GET | /api/v1/stream/thumbnail/movie/{id} |
Movie poster |
| GET | /api/v1/stream/thumbnail/series/{id} |
Series poster |
| GET | /api/v1/stream/thumbnail/album/{id} |
Album cover |
Seeking example:
GET /api/v1/stream/movie/1
Range: bytes=0-1048576
🔍 Search
GET /api/v1/search?q=batman
Returns movies, series, artists and tracks matching the query.
📚 Library
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/library/scan |
Trigger media scan |
| GET | /api/v1/library/scan/status |
Scan progress |
| GET | /api/v1/library/stats |
Total counts |
| GET | /api/v1/library/config |
Current config |
| POST | /api/v1/library/config |
Update media paths |
Building a Client
Any HTTP client works. Example with JavaScript:
const BASE = "http://your-server:8200";
// List movies
const movies = await fetch(`${BASE}/api/v1/movies?page=1&limit=20`).then(r => r.json());
// Stream a movie in <video>
document.querySelector("video").src = `${BASE}/api/v1/stream/movie/${movies[0].id}`;
// Search
const results = await fetch(`${BASE}/api/v1/search?q=inception`).then(r => r.json());
License
MIT — free to use, fork and build on.