isputnik-video
Docker app from isputnik-video's Repository
Overview
Readme
View on GitHubisputnik.video
An add-on for isputnik.home:
its video engine. TV shows and movies, scanned, described and played behind the
home server, which owns every screen and every library. It requires the
isputnik.home container, is installed beside it and is reached only through
home's /video gateway; this server has no pages and does nothing on its own.
How the two fit together: home's docs/video-architecture.md (short) and
docs/apps-platform-plan.md (the whole plan, phases and contract).
Status: 0.14.0, alpha. Catalog, library sync and playback work, with each person's progress (resume, next episode, Continue watching). A file a browser plays as it is goes as it is; the rest are converted to HLS as they play — the sound to AAC, the picture to H.264 only when a browser can't show it. A film with several sound tracks plays the one chosen; subtitles inside it or beside it are offered too (text as WebVTT, images burned in). Posters come from beside the files, and from TMDB with the admin's key; films that belong together are grouped into sets, from the .nfo files or TMDB's collections.
The contract, from this side
- Reached only through home's gateway under
/video. Every request carries the person's identity inX-Isputnik-*headers signed withGATEWAY_SECRET; without the secret a request is anonymous. X-Isputnik-Librarieslists the libraries the person may see. The engine keeps no users or permissions of its own and filters everything by that list.X-Isputnik-Profile-Id, when present, names the household viewing profile the person is watching as: watch history (progress, Continue watching, next up) is then that profile's, whoever is signed in.DELETE /video/api/admin/history/profiles/:idforgets a deleted profile's history.- Home tells the engine about libraries (
PUT/DELETE /video/api/admin/libraries/:id,POST …/sync); a library missing from a sync is only detached, kept 30 days. - Home reads its events, log and a database copy for its backups; the engine never calls home.
| Route | Who | What |
|---|---|---|
GET /video/api/health |
anyone | { ok, version } |
GET /video/api/me |
signed | who home says this is, and which libraries |
GET /video/api/libraries |
signed | the libraries this person may see |
GET /video/api/shows, /shows/:id |
signed | shows, then seasons and episodes |
GET /video/api/movies, /movies/:id |
signed | movies |
GET /video/api/play/:id?audio= |
signed | an episode or movie for the player: how it plays (playback: direct, remux or transcode, and its address) with the sound track asked for, its audioTracks, where to resume, what is next |
GET /video/api/stream/:id |
signed | the file, with byte ranges |
GET /video/api/hls/:id/t<track>/index.m3u8, /:n.ts |
signed | the film as HLS with that sound track, its segments cut as they are asked for |
DELETE /video/api/hls/:id |
signed | the player has gone: stop converting |
PUT /video/api/progress/:id |
signed | { position, duration, watched? } — this person's place in it |
GET /video/api/continue |
signed | left halfway, and the next episode of a show, newest first |
GET /video/api/admin/libraries |
admin | every library with counts and scan state |
PUT /video/api/admin/libraries/:id |
admin | create or change a library (scans it) |
DELETE /video/api/admin/libraries/:id |
admin | delete it and its catalog |
POST /video/api/admin/libraries/sync |
admin | home's whole list: others are detached |
POST /video/api/admin/libraries/:id/scan |
admin | scan now |
GET /video/api/admin/folders?path= |
admin | folders under MEDIA_ROOT, for the picker |
GET /video/api/admin/events, /log |
admin | the admin's window |
GET /video/api/admin/backup |
admin | the whole catalog as one SQLite copy |
POST /video/api/admin/restore |
admin | puts a copy home holds back, at once, in one transaction (application/vnd.sqlite3, X-Isputnik-Backup-Version); a newer copy is refused, and so is any restore while a scan or metadata pass runs. Home's gateway refuses this path: only its Backup page calls it |
GET, POST /video/api/admin/restore/undo |
admin | describes the catalog the last restore replaced (<db>.pre-restore), and puts it back once |
GET /video/api/admin/disks |
admin | the disks the libraries, catalog, posters and conversion folder sit on, one per mounted folder (home's Dashboard) |
Library layout
Show (Year) [imdbid-tt…]/Season 01/Show (Year) S01E01 - Title.mkv (+ .nfo, tvshow.nfo)
Movie (Year) [tmdbid-…]/Movie (Year).mkv (+ movie.nfo)
Movie (Year)/Movie part1.avi, Movie part2.avi one film in two files
Set name/First film.mkv, Second film part-2.mkv a set of films
The layout Jellyfin and Kodi read. .nfo files come first; names fill in the
rest, including release names as they are downloaded. A file written in the last
two minutes is left for the next scan, so a copy in progress is never catalogued.
A movie folder holds one film unless its files say otherwise. Names that differ
only by a part number counting from 1 (part 2, pt2, CD2, disc 2, часть 2,
серия 2) are one film in parts, played in turn. Other files at least a fifth of
the biggest's size are films of their own, in a set named after the folder and
ordered by any part number in their names. Trailers and extras are left out by
name (-trailer, Extras/), and a movie.nfo says the folder is one film.
Configuration
| Variable | Default | |
|---|---|---|
GATEWAY_SECRET |
unset | from home's Control panel → Apps → Setup; required in production |
MEDIA_ROOT |
data/media |
the video folders, mounted read-only (image: /media) |
DB_PATH |
data/video.sqlite |
the catalog (image: /config/video.sqlite) |
PORT / HOST |
4300 / 127.0.0.1 |
|
TRANSCODE_PATH |
temp folder | where ffmpeg writes segments while someone watches (image: /transcode); finished ones move into memory up to the share set on home's Apps → Installed, the rest stay here; emptied on start |
ART_PATH |
art beside DB_PATH |
posters, backdrops and stills fetched from TMDB (image: /config/art); not in backups — fetched again |
FFMPEG_PATH / FFPROBE_PATH |
on PATH |
the image installs both; a checkout uses the ffmpeg-static dev dependencies |
LOG_LEVEL |
info |
|
DEV_USER |
dev:Developer |
development without a secret: an admin who sees every library |
Running it
The image is ghcr.io/isputnikdotnet/isputnik.video (what the Unraid template
pulls) and, the same bytes, isputnikdotnet/isputnik.video on Docker Hub; every
release tag publishes both, and latest is the newest release. Mount /config
(the catalog) and /media (the video share, read-only) — and, if you like,
/transcode on RAM or a fast disk — then:
- In home, Control panel → Settings → Apps → Video: Generate secret and copy
it; paste it here as
GATEWAY_SECRET. The container won't start without it. - On the same page, save the address:
http://<host IP>:4300with the port published,http://isputnik-video:4300on a user-defined Docker network shared with the isputnik container, orhttp://<its IP>:4300on br0 with a fixed IP. Test connection says Paired. - Add a library: Control panel → Library → Libraries → Add library → Video.
Unraid — the repository carries a Community Applications template,
isputnik-video.xml, listed in CA as isputnik-video. It
publishes port 4300 on bridge (safe: without the secret every request is
answered 401), maps /config and the read-only video share, offers /transcode
and /dev/dri for an Intel GPU, and asks for the gateway secret, which is made
in home first because the field is required.
Home's guide docs/users/apps.md has the whole walk-through.
Development
npm install
npm run dev # :4300, the developer identity, data/ under the repo
npm test
npm run typecheck && npm run lint
License: AGPL-3.0-only.
Requirements
Categories
Download Statistics
Related apps
Explore more like this
Explore allDetails
ghcr.io/isputnikdotnet/isputnik.video:latestRuntime arguments
- Network
bridge- Shell
sh- Privileged
- false
- Extra Params
--stop-timeout=30
Template configuration
The port the isputnik container reaches the engine on: enter http://[your Unraid IP]:[this port] as the Video address in isputnik.home (Control panel, Settings, Apps). Not for browsers: video is watched inside isputnik.home. On br0 with a fixed IP, or on a user-defined network shared with the isputnik container, this mapping is not used and the address is the container's own IP or name with port 4300.
- Target
- 4300
- Default
- 4300
- Value
- 4300
Stores the catalog: shows, seasons, episodes and movies found in the video folders, posters and each person's progress (a SQLite database and a picture cache). Keep it apart from the isputnik container's appdata. isputnik.home's backups include a copy of the database.
- Target
- /config
- Default
- /mnt/user/appdata/isputnik-video
- Value
- /mnt/user/appdata/isputnik-video
The share that holds your shows and movies, mounted read-only: the engine never writes to it. Each video library is a folder under it, for example Shows or Movies, chosen in isputnik.home when the library is added.
- Target
- /media
- Default
- /mnt/user/data/video
- Value
- /mnt/user/data/video
Optional. Where a video is converted while someone watches it (a few hundred MB per viewer, deleted as they go). Point it at RAM (/tmp/isputnik-video) or a cache-pool folder to keep it off the array; left empty, it stays inside the container.
- Target
- /transcode
Optional. /dev/dri to convert video on an Intel CPU's graphics (Quick Sync) instead of the CPU: several viewers at once for little CPU. Leave empty to convert on the CPU. Settings, Video in isputnik.home shows what was found.
- Target
- /dev/dri
The secret isputnik.home signs its requests with, so this engine knows who is signed in. Make it first, in isputnik.home on Control panel, Settings, Apps, Video (Generate secret; it is shown once), and paste it here. Required: the engine refuses to start without one, or with one shorter than 32 characters. Everything else about video is managed inside isputnik.home.
- Target
- GATEWAY_SECRET
User ID the engine runs as. It runs unprivileged (not root); on first start it takes ownership of the Config & Data path as this user. This user must be able to read the Video Folders. 99 (nobody) matches the default owner of an Unraid share.
- Default
- 99
- Value
- 99
Group ID the engine runs as. 100 (users) matches the default group of an Unraid share.
- Default
- 100
- Value
- 100
trace, debug, info, warn, error, fatal or silent. isputnik.home shows this log and the engine's own event record under Control panel, Overview, Logs.
- Target
- LOG_LEVEL
- Default
- info
- Value
- info