

Oblecto
Oblecto is a self-hosted media server for the movies and TV shows you already own. It indexes your folders, fetches metadata and artwork, and streams to its own web app and to Jellyfin apps.
Features
- Movie and TV libraries, identified and kept up to date in the background.
- Metadata and artwork from TMDb, TVDB and fanart.tv, with cast and crew, person pages and related titles. Oblecto ships with the project’s API keys; you can use your own.
- Movie pages include trailers, regional age certifications, full crew, IMDb/TMDB links, viewing progress and estimated finish times. Expand Available files → Audio and subtitles for each version’s languages, commentary and accessibility labels.
- Use the copy button under Available files to get a direct HTTP link to the original file for an external player. Embedded tracks and codecs are preserved; links expire after 30 minutes of inactivity by default.
- Series and episode banners use the same focused layout. Shows offer trailers, favourites and a private watchlist; saved-show filters are in TV Shows. Below the banner, viewing progress counts playable library episodes. Library managers can open More series actions → Library tools for episode matching, separate from the viewing page. This workspace matches TMDB episode IDs across different season orders, flags uncertain entries for review, and separates specials and future releases from absent regular episodes. Season menus can play the first unwatched episode or update your watch history after confirming the scope.
- Episode pages show remaining and estimated finish time, nearby episodes and a next-unwatched shortcut. Expand Chapters to play from a timestamp when chapter metadata exists. Full crew, regional series content ratings and external provider links sit below the banners.
- In Account → Language & playback, choose Episode spoilers to hide unwatched artwork and synopsis, optionally titles too. Reveal individual episodes temporarily when needed; watched episodes remain visible.
- Movie banners keep playback, trailers and the watchlist bookmark together. Open More (⋯) to start over, change watched state or save a favourite; genres and provider links are under About this movie, and technical badges are under Available files. Use the Movies library’s Watchlist and Favourites filters to find saved titles. Movie favourites are shared with Jellyfin apps; watchlists stay separate from watched state.
- Movie and series genre filters match whole genre names in both native and Jellyfin libraries: selecting Comedy does not also select Dark Comedy.
- A web app with browsing, search, continue watching, a full player and remote control of other devices. Progress and library changes show up as they happen. Next-episode previews use the show-page card artwork and episode details, with a borderless credits indicator, a subtle countdown strip and small text actions. They appear at terminal credits or, when markers are unavailable, in the final 30 seconds; the end screen also offers the next episode. By default, after 90 minutes without interaction, the current episode finishes and “Are you still watching?” must be confirmed before autoplay continues. Mouse movement, touch, keyboard input and remote playback commands count as interaction; automatic episode changes do not. Disable this safeguard under Account → Preferences → “Ask if I’m still watching”.
- Direct play, and on-the-fly conversion to HLS with FFmpeg when a device needs it.
- A Jellyfin-compatible API on port 8096, so Jellyfin apps on phones, TVs and desktops can sign in, browse, keep favourites and play.
- Accounts with groups and permissions, per-user preferences and avatars, and an optional profile picker on the local network.
- Personal viewing statistics and full session history, plus administrator library and playback-health dashboards. Per-folder title counts, indexed files, known storage and problem counts appear in Settings → Statistics and beside folders in Settings → Libraries; overlapping folders include the same files. Open Statistics from the account menu, or Settings → Statistics with
statistics.view. Tracking begins after upgrade; see metric definitions and retention.
- A problem files page for anything that could not be identified or read, with retry.
- Optional federation between Oblecto servers, with mutual pairing, library synchronization and remote playback, plus seedbox import.
Trailers and age certifications load from TMDB when a movie page opens and are cached for seven days. Failed refreshes keep the last successful data. Trailer players load only when opened. The certification region initially follows your browser’s locale when it includes a country; choose another region under About this movie. The country is shown beside the classification, and a missing regional certification is shown as unavailable.
Planned for later releases: editing metadata by hand, subtitle files beside the video, automatic library scans, and music. See PLAN.md.
Install
Oblecto needs Node.js 24 or newer, FFmpeg, and guessit (python3-guessit on Debian and Ubuntu, or pip install guessit).
With npm
npm install -g oblecto
oblecto init # writes /etc/oblecto/config.json with a random secret
oblecto adduser USERNAME - "Your Name" [email protected] Administrators
oblecto start
oblecto adduser asks for the password when you pass -. Then open http://localhost:8080 and sign in. Add your library folders under Settings.
With SQLite, Oblecto uses the native sqlite3 module when its binary is installed, and Node’s built-in node:sqlite otherwise. The native module keeps the server responsive during long queries, which matters for large libraries. npm 12 skips the step that installs its binary, so to get it, allow that step:
npm install -g --allow-scripts=sqlite3 oblecto
The startup log says which one is in use. Installs from a checkout and the Docker image get the native module on their own.
To keep your data somewhere else, run oblecto init --config-dir DIR and set OBLECTO_CONFIG_PATH=DIR/config.json for every later command.
As a service
contrib/oblecto.service runs Oblecto as its own user under systemd. The install steps are at the top of that file.
With Docker
docker run -d --name oblecto \
-p 8080:8080 -p 8096:8096 \
-v oblecto-data:/etc/oblecto \
-v /path/to/movies:/movies:ro \
-v /path/to/shows:/shows:ro \
ghcr.io/robinp7720/oblecto
docker exec -it oblecto oblecto adduser USERNAME - "Your Name" [email protected] Administrators
The first start writes a config into the /etc/oblecto volume. Everything Oblecto keeps lives there: config, SQLite database, artwork and logs.
Library browsing uses indexed queries and database-aggregated facets. Facets are cached per viewer and filter set for up to 30 seconds, with invalidation after relevant writes. Migration 0015 adds the supporting indexes; SQLite refreshes planner statistics after migration and runs bounded optimization at startup and hourly. The web app loads pages and playback on demand. Unset playback quality preferences use Auto, starting at a low rendition and adapting to bandwidth; saved Original and fixed-quality choices are preserved. Compatible H.264 video can be copied while unsupported audio is converted to AAC. See streaming diagnostics for preparation and startup measurements.
Configuration
Oblecto reads OBLECTO_CONFIG_PATH, or /etc/oblecto/config.json. Anything the file leaves out takes its default from res/config.json. Most settings can be changed in the web app under Settings.
| Setting |
What it does |
server.port |
Web app and API port (8080) |
jellyfin.enabled, jellyfin.port, jellyfin.host |
The Jellyfin-compatible API (on, 8096, all interfaces) |
jellyfin.serverName, jellyfin.loginDisclaimer, jellyfin.customCss |
What Jellyfin apps call the server (Oblecto), text under their sign-in form, and extra CSS for the Jellyfin web client. Settings → Jellyfin apps in the web app edits these and the three above; administrators can also change the first three from a Jellyfin app’s dashboard |
database |
sqlite with storage for the file, or mariadb/mysql with host, username, password and database |
database.migrateOnStart |
Update the database schema when Oblecto starts (on) |
movies.directories, tvshows.directories |
Library folders |
themoviedb.key, tvdb.key, fanart.tv.key |
Metadata and artwork API keys (the project’s, unless you set your own) |
authentication.secret |
Signs sign-ins; oblecto init generates it |
authentication.tokenLifetimeDays |
How long a web sign-in lasts (30) |
authentication.profilePicker, localPasswordlessLogin, allowPasswordlessLogin |
Sign-in without typing a username or password on the local network (all off) |
authentication.localSubnets, trustProxy |
What counts as the local network, and whether to trust X-Forwarded-For |
server.corsOrigins |
Other web origins allowed to call the APIs from a browser (none) |
logging |
Log directory (beside the config file), level, maxSizeMB, maxFiles |
indexer.runAtBoot, cleaner.runAtBoot |
Scan the libraries, or clean up missing files, at every start (off) |
queue.concurrency |
How many background jobs (identifying, metadata, artwork) run at once (1) |
files.doHash, fileExtensions.video |
Hash files to find duplicates (on), and which extensions count as video |
ffmpeg.pathFFmpeg, ffmpeg.pathFFprobe |
FFmpeg and ffprobe to use, if not the ones on PATH |
streaming.trickplay, streaming.trickplayInterval, streaming.detectSegments |
Generate seek thumbnails (on), every 10 seconds (1–60); detect intro/credit segments (on). Existing libraries: Settings → Maintenance → Analyse playback |
streaming.encoderMode |
segment (default) or opt-in window for sequential HLS production in bounded 12-second runs; see performance acceptance in streaming |
streaming, transcoding |
Playback cache, encoder limits and hardware encoding; see docs/STREAMING.md |
assets, artwork |
Where artwork, avatars and seek thumbnails (assets.trickplayLocation) are stored, and the sizes artwork is scaled to |
federation, seedboxes |
Federation with other Oblecto servers (docs/FEDERATION.md) and seedbox imports |
web.enabled |
Serve the web app (on) |
Oblecto refuses to start without a config file or a signing secret, and says why. Startup awaits database migration, group initialization and playback cache preparation before opening the APIs. If required startup fails, acquired services and the database are closed.
On SIGINT or SIGTERM, Oblecto stops accepting requests and polling seedboxes, drains accepted background jobs (including their follow-up work), ends playback, and closes the database last. Cleanup continues if a service fails, and failures produce a nonzero exit. The shutdown deadline is 15 seconds; work still running at that deadline is interrupted. Requests arriving on existing HTTP connections during shutdown receive HTTP 503.
Groups and permissions
The first start creates two groups. Administrators may change settings, manage users and libraries, and run maintenance. Users may watch. Put people in groups on the Users settings page, or from the command line:
oblecto usergroup USERNAME Administrators
Oblecto will not delete or demote the last administrator.
Command line
oblecto start | start-tui Run the server, or with a terminal dashboard
oblecto init [--config-dir DIR] Write a config, artwork folders and federation keys
oblecto init database | assets Create just the database, or just the artwork folders
oblecto migrate [--status] Update the database (also runs at start)
oblecto adduser USERNAME - NAME EMAIL [GROUP]
oblecto changepassword USERNAME
oblecto removepassword USERNAME
oblecto usergroup USERNAME GROUP
oblecto deluser USERNAME
Upgrading
Back up your database, install the new version and start it. See docs/UPGRADING.md for what changes and what to check.
Development
git clone --recurse-submodules https://github.com/robinp7720/Oblecto.git
cd Oblecto
npm ci
npm run build:web
OBLECTO_CONFIG_PATH=/path/to/dev-config.json npm run dev
npm run verify # source lint, backend + test typecheck, and unit/integration tests
npm run build builds both web apps and the server into dist/. npm run test:network runs the tests that call the real metadata services. The Playwright suites run with npm run test:player:ui and npm run test:playback:browser.
To run the web app from Vite’s dev server against a local Oblecto, add its origin to server.corsOrigins.
Building a desktop client or handing implementation to another agent? Start with the desktop client guide, then use the complete endpoint index and response models. They cover authentication, browsing, playback lifecycle, progress, remote control, examples and an acceptance checklist.
API references: REST, realtime, streaming, federation, and Jellyfin compatibility.
Security
See SECURITY.md for what Oblecto protects, what it leaves public on purpose, and how to report a problem.
License
AGPL-3.0-or-later. The bundled Jellyfin web client is GPL-2.0, from jellyfin-web.
Powered by

评论