# What Mediarium does today A plain comparison of what Mediarium does **today** against the apps it can replace or sit beside, written from the source code. - **Snapshot:** 2026-10-11, Mediarium 3.0.0 (database migrations up to `0170`; see the [changelog](../CHANGELOG.md)). Read every "No" as "not found when this was written". If it matters to you, look in `internal/` and `web/src/pages`. - **How each row was judged:** Yes = implemented and reachable in the UI or API. Partial = something real exists but it is narrower than the reference app. No = not found. The evidence is a package, file, endpoint or guide you can open. - **Reference apps** are described from general knowledge of those projects and may be out of date for their newest versions. Uncertain claims are worded loosely or left out. - Abbreviations: **Rad** Radarr, **Son** Sonarr, **Lid** Lidarr, **Pro** Prowlarr, **Sab** SABnzbd, **qB** qBittorrent, **Baz** Bazarr. - In Mediarium's screens, indexers are called **Indexers**. ## 1. Where Mediarium stands in one paragraph Movies, TV, music, ebooks and audiobooks all work end to end (music, ebooks and audiobooks once you switch them on; see 2.4b and [books.md](./books.md)). That covers TMDB metadata; one search across Newznab/Torznab indexers and definition-based torrent sites (the community Cardigann definitions, downloaded on demand); grabbing; a built-in Usenet client (multiple servers, PAR2, native RAR and ZIP unpacking, `7z` only for `.7z`); and a built-in BitTorrent engine (with an embedded WireGuard VPN and kill switch), or a torrent client or debrid service you already use. It also has hardlink import with naming presets, quality profiles with custom formats (and a TRaSH import), delay profiles, upgrade hunting, a blocklist with automatic retry, monitoring, tags, several folders per kind of media, a calendar, a wanted list, import lists that sync on a schedule, a request portal, subtitles, many kinds of notification, media server refresh, family accounts with single sign-on options, backups (also to the cloud), a clean-up of the downloads folder, health checks and a first-run wizard. What is still thin or missing, stated plainly: files are not unpacked while they download (Usenet downloads unpack when they finish); downloads can't be dragged to reorder; a delay profile is one setting for the whole library (none per title, none for music or books); there are no per-indexer query limits, no per-indexer tags and no category mapping you can edit; there is no Last.fm scrobbling (ListenBrainz works); no comics or manga, no podcasts, and no adult content module; no theme songs or extras; watch state is read from your media server every six hours, not pushed by a webhook; and IMDb and Letterboxd lists are read from the exported file, not synced live (those sites don't allow it). Section 3 has the full list. Family accounts exist. An administrator can add basic-user and viewer accounts (see [accounts.md](./accounts.md)). RAR (RAR4 and RAR5, including multi-part sets) and ZIP are unpacked natively in Go, so they work the same everywhere. Only `.7z` (also when it is split into `.7z.001`, `.7z.002`, ...) uses the `7z` tool, which the Docker image includes. ## 2. Matrix ### 2.1 Library, search and automation (Radarr / Sonarr territory) | Feature | In Mediarium today | Evidence | In reference apps | |---|---|---|---| | Monitoring (movie, show, season, episode) | **Yes** | `PUT /api/movies/{id}/monitored`, `/api/series/{id}/monitored`, `/seasons/{season}/monitored`, `/episodes/{id}/monitored`. Two optional switches stop monitoring a movie once it is downloaded, and a show once it has ended and every episode is in (`library.unmonitor_downloaded`, `library.unmonitor_finished_shows`) | Rad, Son | | Quality profiles (ordered tiers, cutoff, upgrade-until) | **Yes** | `internal/quality/profile.go` (15-tier ladder), `/api/quality-profiles` CRUD, per-title profile; five built-in presets: Cinema recordings, Any, 720p, 1080p (default) and 4K & over, all starting with upgrades off; "Skip bad releases" is on in every profile (whole discs, 3D, upscales, burned-in subtitles, poor re-encode groups) and a fixed release (PROPER, REPACK) wins over the broken one; a profile can refuse season packs; fallback profiles (see [quality-profiles.md](./quality-profiles.md)) | Rad, Son | | Custom formats (spec-based scoring: release group, HDR, codec, language, regex) | **Yes** | `internal/api/custom_formats.go`, `/api/custom-formats` (CRUD and `/test`), scores per profile with a minimum score and an upgrade-until score, a Score column in interactive search, with a details row per release (the matched formats and preferred terms with their scores, the profile's limits, why an automatic search would skip it and why it was not the best match). Formats from Radarr, Sonarr and the TRaSH Guides import unchanged: `GET /api/trash-guides/{app}`, `POST .../formats` and `.../profiles` (ready-made profiles included), or paste their JSON. An advanced option, hidden until "Show advanced options" is on ([quality-profiles.md](./quality-profiles.md#custom-formats)). The TRaSH import is a button you press, not a scheduled sync | Rad, Son (Recyclarr syncs TRaSH ones) | | Quality definitions (min/max size per quality) | **Yes** | size limits per quality in MB per minute, with a reset to defaults (`quality.size_limits`, off by default); releases outside them are skipped and marked in the list. On top of that, a built-in minimum per quality catches fakes (`internal/quality/size.go`) and a profile can set the largest size (`max_size_gb`) | Rad, Son | | Delay profiles (wait N minutes for a preferred protocol) | **Partial** | one profile for the whole library: preferred protocol, minutes to wait for Usenet and for torrents, and "don't wait for the best quality" (`internal/delay`, setting `search.delay_profile`, `GET`/`PUT /api/search/delay`, `GET /api/search/waiting`). Held releases show on Wanted and on the title page. Movies and shows only. No profile per title or per tag, none for music or books. Off by default | Rad, Son | | Per-title protocol preference (usenet / torrent / both) | **Yes** | `PUT /api/movies/{id}/sources`, `library.default_sources` | partly (via delay profiles) | | Indexer management (add, test, edit, enable/disable, delete) | **Yes** | `/api/indexers` GET/POST/PUT/DELETE, `/test`, `/{id}/test`, `/{id}/enabled`. Newznab and Torznab APIs, plus sites from the definition list (`kind: cardigann`) with their own settings; passwords, cookies and keys stored encrypted and never returned. A failed test of a definition-based site shows on the dashboard | Rad, Son, Pro | | Indexer definitions engine (Cardigann / hundreds of trackers) | **Yes** | `internal/indexers/cardigann*.go`, `definitions.go`, `GET /api/indexer-definitions`. Runs the community Prowlarr/Indexers definitions (schema v11, downloaded when the site list is opened, none bundled): login by form, POST, GET or cookie with CSRF inputs and error/test selectors, HTML, JSON and XML results, the template language and the common filters, magnet and `.torrent` downloads through the signed-in session, per-site request delay, optional FlareSolverr for Cloudflare. You can add your own definition file (`POST /api/indexer-definitions/custom`). Almost all of the current definitions pass validation, and the site list marks the rest as unsupported, with the reason. Not supported: CAPTCHA logins, look-around regexes in `regexp` filters (skipped in `re_replace`), a handful of invalid selectors. Tested against local fixture sites; expect some real sites to need fixes | Pro | | Indexer priorities, per-indexer tags, seed rules | **Partly** | priority 1 to 50 (lower first, default 25) breaks ties between equal releases (`PUT /api/indexers/{id}/priority`); seed rules per indexer for the built-in torrent client (`PUT /api/indexers/{id}/seed-rules`). No tags on indexers | Rad, Son, Pro | | Indexer back-off, health and statistics | **Yes** | after 3 failures in a row an indexer is left out of searches for 5 minutes, doubling up to 6 hours, with the reason and the time shown on the card and in Health, and a **Try again now** button (`POST /api/indexers/{id}/resume`, `internal/api/indexer_health.go`); searches, failures, success rate, releases found and grabs per indexer on the Statistics page (`GET /api/stats/indexers`, migration `0071`). See [indexers.md](./indexers.md) | Rad, Son, Pro | | Per-indexer query limits, category mapping | **No** | not found. Searches use fixed Newznab categories for each kind of media; definition-based sites map their own categories inside the definition. Nothing to edit per indexer | Pro | | Usenet retention | **Yes** | tell Mediarium how many days your provider keeps posts (`downloads.retention_days`); automatic searches skip older posts and the release list marks them ([downloads.md](./downloads.md#usenet-retention)) | Sab (article age), Pro | | Sync indexers to other apps | **n/a** | Mediarium is one app; can import Torznab/Newznab URLs from Prowlarr manually | Pro | | RSS sync | **Partial** | `rss-sync` job (every 15 min by default, a setting; `internal/api/automation.go`) runs an empty-query search on every enabled indexer and matches recent listings to monitored items. It is a listings poll, not a dedicated per-indexer RSS feed; no per-indexer toggle | Rad, Son | | IRC announce (grab at the moment of release) | **Yes** | `internal/announce`, `/api/irc-announce` CRUD, `/test` and a log per connection: Mediarium sits in a tracker's announce channel and downloads a wanted release as it is announced. Four built-in announcement styles, a template editor and a test box, limits per hour and per bot. Only acts on titles already in the library. Off until you add a connection ([irc-announce.md](./irc-announce.md)) | Autobrr (separate app); Rad, Son via other tools | | Scheduled missing / upgrade hunting | **Yes** | `hunt` job (every 6 h by default, a setting), `series-refresh` 12 h (finished shows weekly, others daily), `genre-backfill` hourly (`internal/api/automation.go`, `automation_tv.go`, `genres_job.go`) | Rad, Son | | Manual / interactive search with reject reasons | **Yes** | `GET /api/movies/{id}/search`, `/api/series/{id}/search`, `ReleaseTable.tsx`; "Search now" per row; the list sorts and filters by size, seeders, quality, score, indexer and words | Rad, Son, Pro | | Global cross-indexer search | **Yes** | `GET /api/search`, `POST /api/search/grab`, `web/src/pages/Search.tsx` | Pro | | Calendar | **Yes** | `GET /api/calendar`, `pages/Calendar.tsx`, month and agenda views, filters, and a private iCal feed per account (`/api/calendar/feed/{token}.ics`). Episode air times come from TVmaze (`internal/tvmaze`, setting `metadata.tvmaze_air_times`): an episode with a known time sits on the day it airs in the viewer's time zone and is a timed event in the feed, the rest stay on their date ([library.md](./library.md#air-times-and-the-calendar)) | Rad, Son (with iCal) | | Wanted: missing and cutoff-unmet | **Yes** | `GET /api/wanted`, `pages/Wanted.tsx` | Rad, Son | | Rename / organize on import (token naming, presets) | **Yes** | `internal/organizer/naming.go`, presets plex/jellyfin/kodi/minimal/custom, Radarr and Sonarr token names, a builder with ready-made formats and a token list, live preview `GET /api/settings/naming-preview` | Rad, Son | | Bulk rename of an existing library | **Yes** | preview, then rename the ticked files with their subtitles (`GET`/`POST /api/rename`, Settings > Library) | Rad, Son | | Import an existing library | **Yes** | `POST /api/library/scan`, `/api/library/import`, `GET /api/library/import/active`, `pages/ImportLibrary.tsx`. Confirming registers every title at once in one transaction (no lookups); a background worker (`internal/api/import_worker.go`) then fills in details, resumes after a restart and retries failures. Imported titles are added unmonitored and set to leave what you have alone; two switches on the review page (both off) start monitoring, and for shows also look for missing episodes ([import-library.md](./import-library.md)) | Rad, Son | | Change many titles at once (Library select mode) | **Yes** | administrators pick titles (Shift-click for a range, "Select all N in this view") and monitor, switch better versions, set the quality profile, downloaders or tags, search now (monitored and missing only, 25 at a time) or remove them, each with one request in one transaction: `PUT /api/library/bulk/{monitored,no-upgrade,profile,sources,tags}`, `POST /api/library/bulk/{search-now,remove}`, and `/api/music/bulk/{follow,profile,remove}` for artists; files are deleted only when the request says so ([library.md](./library.md)) | Rad, Son | | Move many titles to another library folder | **Yes** | `POST /api/library/move-files/preview` and `/api/library/move-files` (`internal/api/move_files.go`): change the folder only for new files, or move the files already there too (copied and checked first when it is another drive) | Rad, Son (mass editor) | | Move over from other apps | **Yes** | `internal/migrate`, `POST /api/migrate/preview`, `/api/migrate/run`, `GET /api/migrate/status`: twelve apps (Radarr, Sonarr, Prowlarr, SABnzbd, NZBGet, Jackett, NZBHydra2, Overseerr/Jellyseerr, Ombi, Bazarr, Medusa, SickChill), read-only on their side. Library (files registered in place), monitored flags, quality profile matching, indexers, Usenet servers, requests and subtitle languages ([migrate.md](./migrate.md)). Screen: Settings → System → Move from other apps. | Rad, Son, Pro, Sab | | Manual import / manual match for unmatched releases | **Yes** | Activity > Import a file by hand: pick a file in the downloads folder, or in any folder you choose, and the movie or episode it is; hardlink, copy or move (`/api/manual-import`) | Rad, Son | | Multiple root folders | **Yes** | more movie and TV folders under Settings > Library > Folders and file names; the Add dialog and each title's page choose the folder (`GET /api/library/folders`, `PUT /api/movies/{id}/folder`, `PUT /api/series/{id}/folder`, `internal/api/folders_extra.go`); imports, renaming, the recycle bin, disk checks and the Radarr/Sonarr-compatible root folder list know about them | Rad, Son | | Several qualities of one title (a 4K copy next to 1080p) | **Yes** | opt-in second copies of a movie or show, each with its own profile, downloads and upgrades, kept in a copies folder of its own (`internal/api/copies.go`, `movies.copy_of`/`series.copy_of`; see [library.md](./library.md#second-copies-two-qualities-of-one-title)) | Rad, Son (a second instance) | | Tags | **Yes** | tags on movies and shows (up to 20 per title) set on the title, when adding, on a selection, on an import list or in the Library filter; every tag becomes a collection on Plex, Jellyfin and Emby; cleanup rules can keep tagged titles (`GET /api/tags`, `PUT /api/movies/{id}/tags`, `PUT /api/series/{id}/tags`, `PUT /api/library/bulk/tags`). Not on indexers or notifications | Rad, Son, Pro, qB | | Import lists (automatic add from a list) | **Yes** | `internal/importlists`, `/api/import-lists` (CRUD, `/preview`, `/{id}/run`, `/{id}/forget`): Trakt (lists, watchlists, charts), TMDB, MDBList, Simkl (your own Plan to Watch, Watching and Completed lists, after a sign-in with a code), and IMDb and Letterboxd from an exported file, read on a schedule from every hour to every week. Each list has a quality profile, folder, tags, a minimum rating and year, and an "add at most N at a time" limit. The Plex watchlist of each account (`/api/plex-watchlist`) is checked every 20 minutes. IMDb and Letterboxd have no open API, so those two are not live ([lists.md](./lists.md)) | Rad, Son | | List exclusions | **Yes** | "Not interested" on Discover (`/api/exclusions`); import lists skip those titles | Rad, Son | | Season packs, multi-episode releases | **Yes** | `internal/parser`, `pipeline_tv.go`, `automation_tv.go`; a grab marks the episodes it will deliver as downloading when it is queued, and automatic searches never grab an episode that is already downloading, so a pack's episodes are only tried singly after the pack failed (`grab_claim.go`). A profile can turn season packs off | Son | | Anime / absolute numbering / daily shows / series types | **Yes** | a show's episode numbering is standard, anime (absolute numbers) or daily (air dates), guessed when it is added (`internal/api/series_type.go`, parser `Absolute`/`AirDate`); specials are searched and grabbed one at a time, by `S00Exx` or by their title, once ticked | Son | | Scene numbering and anime mapping | **Yes** | TheXEM scene numbers, anime-lists mapping, AniList, AniDB and MyAnimeList links, a show's other names, and a Refresh mapping button (`internal/animemap`, `GET /api/series/{id}/numbering`, `POST .../numbering/refresh`, setting `numbering.lookup`); "Add anime groups" adds starter release-group terms to a profile ([library.md](./library.md)). Follows TheTVDB's numbering for scene episodes, which differs from TMDB for a few shows | Son | | Audio languages, original-language audio | **Yes** | a list of languages, best first, and "Original language of the title" (`quality.language`, `internal/api/original_language.go`); a release with two or more audio tracks counts when one is on the list, and an optional switch (`quality.language_only`, off by default) takes only releases that say they are in a listed language ([quality-profiles.md](./quality-profiles.md#audio-language)) | Rad, Son (via language custom formats) | | Minimum availability / release-date gating for movies | **Partial** | a film still only in cinemas is not searched automatically: it waits for the digital or disc date TMDB lists, or 90 days after the cinema date when TMDB has none; not held for a profile that takes CAM/TeleSync, and Search now still works. Not configurable per movie | Rad | | Movie collections | **Yes** | a movie's page shows its TMDB collection with **Add the whole collection** and an option to add new films that join it; the Library filters by collection (`GET /api/collections`, `POST /api/collections/{id}/add`, `PUT /api/collections/{id}/follow`, [library.md](./library.md#collections)) | Rad | | Editions | **No** | there is no edition management. The `{Edition Tags}` naming token fills in an edition that the release name states, so Plex's edition naming works | Rad | | Media management: recycle bin | **Yes** | removed files wait in `.mediarium-trash` inside the library folder for 7 days, with Put back (`/api/trash`) | Rad, Son | | Media management: file permissions / chmod / chown | **Yes** (mode; owner from `PUID`/`PGID`) | set the mode of the files and folders Mediarium creates (`library.file_mode`, `library.folder_mode`, `GET /api/settings/file-permissions`, `internal/fileperms`); the container honours `UMASK`. Ownership comes from `PUID`/`PGID` only, no chown setting ([library.md](./library.md)) | Rad, Son | | Media management: existing-file conflict policy | **Yes** | `library.import_conflict_policy` skip / overwrite / overwrite-if-better / ask, atomic replace (`organizer/import.go`) | Rad, Son (differently) | | Media management: hardlink then copy fallback | **Yes** | `organizer/import.go` tries `os.Link` and copies when the link fails for any reason (another drive or mount, or a filesystem without hardlinks). The "same drive" check on the dashboard compares device numbers (`organizer/samefs_unix.go`), so two Docker mounts of one disk can pass it and still copy, which is why the compose file uses one `/data` mount ([INSTALL.md](./INSTALL.md#why-one-data-folder-hardlinks)) | Rad, Son | | NFO and artwork files | **Yes** (off by default) | NFO files and poster, background, logo and season artwork for Kodi, Jellyfin and Emby, written after imports and for the library you already have (`internal/metafiles`, `library.metadata_files`) | Rad, Son | | Health checks | **Yes** | `GET /api/health`, `internal/api/health.go` (missing keys, no indexer, paused indexers, folder problems, VPN, recent failures, titles waiting for subtitles (only while subtitles are switched on), a missing `par2` or `7z`, and a shared Trakt, Simkl or OpenSubtitles key reaching its limit) | Rad, Son, Pro | | Shared-key usage tracking | **Yes** | `GET /api/usage` counts requests and limit hits (HTTP 429, OpenSubtitles 406) per service over 24 hours (`internal/usage`); the dashboard suggests a free personal key when the shared one is busy | none | | Logs and errors | **Yes** | Settings > System > Logs and errors: real problems only (failed downloads, Usenet, indexers, media servers, import, disk and folders, database, notifications), each with a plain explanation and what to try, repeats counted on one row, kept 30 days, copy for support and a text file, optional message on new errors (`internal/problems`, `GET /api/system/problems`; see [logs-and-errors.md](./logs-and-errors.md)) | Rad, Son, Pro (their log pages), Sab (warnings) | | Notifications | **Yes** | `internal/notify`: email, webhook (with your own JSON body), Discord, Telegram, Slack, ntfy, Gotify, Pushover, Matrix, Home Assistant (notify service or webhook), Apprise (any service Apprise knows) and web push to the browser; per-target event choice, quiet hours, a test button and a test log (`POST /api/notifications/test`). Not Notifiarr, and no per-notification tags ([notifications.md](./notifications.md)) | Rad, Son, Pro, Sab, Baz | | Web push and installing as an app | **Yes** | push to a phone or computer from the browser itself with no app or account, encrypted per device (`internal/notify/push.go`, `web/public/push-sw.js`, `GET /api/notifications/push-key`); the web app has a manifest, so it installs to the home screen and opens like an app. Needs https; on iPhone and iPad, add it to the Home Screen first. Long-press shortcuts, tablet and foldable layouts, and a "can't be reached" page when the server is down; no offline mode | none | | Media server connection (Plex, Jellyfin, Emby, Silo, Audiobookshelf, Kavita, webhook) | **Yes** | `internal/mediaservers`, `/api/media-servers`: find servers on the network, sign in with Plex, Jellyfin Quick Connect or a Jellyfin/Emby login (or add one with a token or API key), test, partial library scan of the imported folder after each import (debounced, with path mapping, full-scan fallback), **Refresh now**, "Watch in" links found by TMDB id (`GET /api/media-servers/links`, open to members), dashboard item when a server fails. Any other server can get a JSON message by webhook. See [media-servers.md](./media-servers.md) | Rad, Son (Connect: Plex, Emby/Jellyfin library update) | | History | **Yes** | `GET /api/activity`, Activity page; per title `GET /api/movies/{id}/events` and `GET /api/series/{id}/events`: each search with how many releases were acceptable and why not, the grab and the profile used, download and post-processing steps, failures, blocklisting and retries (see [activity.md](./activity.md)) | Rad, Son, Pro | | Blocklist (auto on bad release, manual, retry next best) | **Yes** | `internal/blocklist`, `/api/blocklist`, `POST /api/queue/{id}/blocklist`. **Retry** on a failed Usenet download repeats post-processing on the files it already has instead of downloading again; one download at a time per movie or episode (a grab by hand while one runs gets 409) | Rad, Son | | Updates and restarts | **Yes** | new-version notice (daily GitHub check, notes, steps for Docker and native), signed **Update now** and overnight install, pushed updates (opt-in, `POST /api/system/update`), restart and safe restart, self-restart when stuck, Docker health check (`internal/updatecheck`, `internal/selfupdate`, `docker/entrypoint.sh`); see [INSTALL.md](./INSTALL.md#updating) and [security.md](./security.md#updating-the-program) | Rad, Son (built-in updater) | | Backup / restore | **Yes** | admin-only `GET /api/system/backup` (consistent `VACUUM INTO` snapshot + `secret.key` + manifest, as a zip) and `POST /api/system/restore` (strict validation, staged, applied on the next start; old files kept in `before-restore-*`), `internal/backup`. Nightly backups kept in `/config/backups`, with optional passphrase-locked copies in S3-style storage or a WebDAV folder, and restore from such a copy (`internal/cloudbackup`, `/api/system/backups/cloud`). Settings and database only, never media | Rad, Son, Pro, Sab, Baz | | API keys and authentication | **Yes** | local accounts, cookie sessions, rate-limited login, `X-API-Key` (`internal/auth`, `/api/auth/api-keys`); read-only keys for a viewer or for monitoring | all | | Two-step sign-in (TOTP) | **Yes** | a six-digit code from an authenticator app after the password, recovery codes, switched on per person (`internal/totp`, `/api/auth/two-step/*`); wrong codes are counted per account | Rad, Son, Pro (not built in) | | External auth (OIDC, LDAP, passkeys, proxy header) | **Yes** | OpenID Connect (Authelia, Authentik, Keycloak, Pocket ID, Google; `internal/oidcauth`), LDAP and Active Directory (`internal/ldapauth`), passkeys (`/api/auth/passkey*`), and sign-in through a reverse proxy's user-name header from a trusted proxy address only (`/api/auth/proxy-signin`). All off until you turn them on; local sign-in can be switched off, and `MEDIARIUM_DISABLE_SSO=1` is the way back in ([accounts.md](./accounts.md#ways-to-sign-in)). No HTTP basic auth | Rad, Son, Pro (forms/basic/external) | | URL base and secrets from files | **Yes** | `URL_BASE=/mediarium` runs the app under a sub-path of a domain; any container variable can be read from a file (`NAME_FILE=/run/secrets/x`) for Docker secrets ([INSTALL.md](./INSTALL.md#running-under-a-sub-path-url-base)) | Rad, Son (URL base) | | Prometheus metrics | **Yes** | `GET /metrics` (also `/api/metrics`), admin only, accepts a bearer API key: wanted counts, library sizes, queue, disk space, health and indexer status ([INSTALL.md](./INSTALL.md#monitoring-with-prometheus)) | Rad, Son via exporters | | Statistics / disk-space overview | **Yes** | Statistics page: library size, titles per quality, downloads per month (counted as they happen, so clearing the history does not change them; **Reset statistics** starts them again, `POST /api/stats/reset`, migration `0223`), charts over time from a daily snapshot (`GET /api/stats/history`), indexer statistics and, with watched status on, what gets watched (`GET /api/stats/library`), plus the dashboard's folder health | Rad, Son | | A title's files on disk, playing a video in the browser | **Partial** | `GET /api/movies/{id}/files` and `GET /api/series/{id}/files` list the title's folder (relative path, size, date, kind: video, subtitle, image, nfo, other). `GET /api/files/stream?movie={id}&path=...` (or `series=`) sends a video file as it is, with seeking, for a `