# JRay A Jellyfin plugin that brings an actor-overlay (think Amazon "X-Ray") feature to your media: pause a movie and JRay shows you which actors are in the scene you paused in. JRay reads "truth" files produced offline by the [scene-actor-extraction](https://github.com/dtourolle/scene-actor-extraction) pipeline (face detection + recognition) and exposes an API to query which actors are present in the scene at a given timestamp. A small overlay, injected into the Jellyfin web client, displays the result when you pause playback. ## Status **Alpha** — JRay works end to end (sidecar truth files, remote truth push, and the pause overlay) but is early software and the truth-file schema may still change. The overlay relies on patching the web client's `index.html`, which is inherently a little fragile across Jellyfin versions (see [Important Notes](#important-notes)). ## Quick Install Add this repository URL in Jellyfin (Dashboard → Plugins → Repositories): ``` https://gitea.tourolle.paris/dtourolle/jRay/raw/branch/master/manifest.json ``` Then install "JRay" from the plugin catalog and restart Jellyfin. ### Required for the overlay: File Transformation JRay's pause overlay needs a script tag in the web client's `index.html`. Install [File Transformation](https://github.com/IAmParadox27/jellyfin-plugin-file-transformation) (repository `https://www.iamparadox.dev/jellyfin/plugins/manifest.json`) **before** installing JRay. It rewrites the page as it is served, so the file on disk is never touched — that survives server upgrades and coexists with other plugins patching the same file. **There is no fallback.** JRay never edits `index.html` on disk: a patch there outlives an uninstall, is silently discarded by a web-client upgrade, and races any other plugin touching the file. Without File Transformation the pause overlay is simply disabled — every other JRay feature works normally, and the plugin's configuration page tells you what is missing and how to install it. Upgrading from an older JRay that did patch `index.html`? It removes its own patch on startup, so there is nothing to clean up by hand. See [SPEC.md](SPEC.md) JR-021/JR-022. ## Features - **Pause overlay** — pause a movie or episode in the web client and see the actors in the current scene, without leaving the player. - **Sidecar truth files** — drop a `Movie.jray.json` next to `Movie.mkv` and JRay picks it up automatically (suffix configurable). - **Remote truth push** — for servers that can't run the extraction pipeline locally, a remote worker can `PUT` truth data over HTTP. Managed (pushed) data takes precedence over sidecar files. - **Work discovery API** — a remote worker can poll for a random batch of library items that still need processing, so the backlog spreads naturally across workers without server-side task tracking. - **Prioritise / ignore rules** — steer that backlog by genre, series, or individual item: ignore what you never want extracted (e.g. anime), or push a series to the front of the queue. - **Coverage overview** — see at a glance how much of your library has actor data, broken down by genre and by media type (film vs TV). - **Extensible "context at time t" envelope** — the per-timestamp response is designed to grow (locations, trivia, …) without breaking existing clients. - **In-memory caching** — loaded truth files are cached with a configurable TTL. - **Toggleable overlay** — disabling the overlay also cleanly removes the injected script from the web client. ## How It Works ``` scene-actor-extraction Jellyfin server web client (offline pipeline) (browser) ┌────────────────────┐ ┌──────────────────┐ ┌────────────┐ │ face detection + │ truth │ JRay plugin │ jray?t= │ pause │ │ recognition │ ───────► │ - sidecar reader │ ◄─────── │ overlay │ │ result_sink_node │ file │ - managed store │ actors │ script │ └────────────────────┘ │ - REST API │ ───────► └────────────┘ │ PUT /Truth (remote) │ - web patcher │ └────────────────────────►└──────────────────┘ ``` 1. The extraction pipeline analyses a film offline and emits a **truth file** listing each actor and the time windows they are present in the film. 2. JRay loads that truth file either from a **sidecar** next to the media (`Movie.jray.json`) or from a **managed store** populated via the push API. 3. On startup JRay injects a small `