Optimisarr

Optimisarr

Docker app from Jellman's Repository

Overview

Optimisarr is a safe media-library optimiser: it transcodes your movies and TV to save space and never deletes or replaces an original until the converted file has passed explicit verification gates. It probes each file, decides whether re-encoding is worthwhile, transcodes to a work directory, verifies the output (decodes cleanly, duration/stream policy match, size actually reduced), then atomically replaces the original and keeps the untouched original in quarantine so any replacement can be rolled back. Supports CPU, Intel QSV/VA-API and NVIDIA NVENC hardware transcoding, integrates with a Sonarr/Radarr media stack, and shows a real-time dashboard with a live queue, per-job logs, and savings stats. Set the media library you want it to watch under /data.

Optimisarr app icon

Optimisarr

Safe, verified FFmpeg transcoding for self-hosted media libraries.

DocsQuick StartHardware Acceleration

Optimisarr is a self-hosted, Docker-based FFmpeg media-library optimiser. It finds eligible video, audio, and image files, transcodes them to reduce storage use, verifies the result, and only then replaces the original.

Built for Plex, Jellyfin, Emby, Sonarr, and Radarr users, Optimisarr supports CPU, NVIDIA NVENC, Intel QSV, and VA-API transcoding. Originals are quarantined for rollback rather than deleted immediately.

Why Optimisarr?

  • Reduce media-library storage without manually batch-transcoding files.
  • Verify output before replacement, with configurable stream-retention, duration, and size-reduction checks.
  • Run one Docker container on a homelab, Unraid-style server, or other self-hosted setup.
  • Pause processing while Plex, Jellyfin, or Emby has active streams.

Optimisarr Queue in dark mode, showing active GPU transcoding

All media shown in screenshots is fabricated test data created for documentation; no copyrighted material is used.

Documentation

Start with the documentation index: getting started, user workflow, configuration, hardware acceleration, reverse proxy, safe replacement, integrations, troubleshooting, glossary, and API reference.

Project status

Optimisarr is early-stage software. Use it on a small test set first and keep backups of media you cannot replace. It is maintained in spare time, so there is no support SLA or promise of a release schedule.

What it does

  • Multiple libraries, each with its own media type (Film/TV/Music/Photo/Other) and rule profile, with a folder-picker for paths. Scanning discovers the file types that match the library (video, audio, or images).

  • Recursive, settling-aware scanning that builds a media inventory (idempotent), with automatic background probing of newly discovered files. Enabled libraries are rescanned on a configurable global interval (one hour by default).

  • ffprobe inspection (codec, resolution, duration, tracks, media kind).

  • Optimisation for video, audio, and still images, each through the same candidate → transcode → verify → quarantine/rollback pipeline.

  • FFmpeg/ffprobe tool detection, liveness, and readiness endpoints. Docker health checks verify database access, required writable paths, and media tools.

  • Svelte 5 + Tailwind sidebar UI (Dashboard, Libraries, Inventory, Queue, Quarantine, Schedule, Settings; Tools live under Settings). Verification reports are available from Queue and Quarantine detail sheets.

  • Queue resource controls: max concurrent jobs, CPU thread limits, and a free work-disk safety pause. The only global scheduling setting is the library scan interval; when work runs is set per library (see auto-optimise below).

  • Per-library auto-optimise windows continuously queue newly eligible files; opt-in auto-replace promotes only fully verified jobs, still quarantining the original first so rollback remains available.

  • Optimisation presets per library (Compatibility H.264 / Balanced HEVC / Efficiency AV1 / Remux), plus Scott's Settings — HEVC with HDR preserved and AAC 96 kbps stereo audio. Optionally re-encode oversized files already in the target codec (e.g. a huge HEVC remux) above a size you set.

  • Exclude files so they are never optimised again — manually from a stuck Queue job, or automatically after repeated failures — managed per library on an Excluded tab. Durable (keyed by path) and reversible; originals untouched.

  • A Dashboard leading with a persistent lifetime space-saved total (resettable), what's in flight, and live CPU/GPU usage while a job encodes.

  • Preview from Inventory or a library's Candidates tab to try the resolved settings on one file before queueing it. Long video previews encode a 60-second sample from the middle of the source, verify against a temporary clipped reference from that same window, and label the report as segment-only; audio and image previews run in full.

  • Video replacement verifies the resolved codec, exact resolution, pixel bit depth, chroma sampling, and encoder profile in addition to full decode, timing, HDR/colour, stream, size, and VMAF gates.

  • Music defaults to AAC 128 kbps in M4A, preserving common attached cover art, tags, and timed lyrics. Opus remains an efficient option for art-free libraries; incompatible artwork/lyrics combinations are rejected before queueing rather than being dropped or failing during muxing.

  • Hardware capability detection for FFmpeg accelerators, CPU encoders, NVIDIA NVENC, Intel QSV, VAAPI, NVIDIA runtime, and /dev/dri mapping.

  • Global encoder mode selection for Auto, CPU, NVIDIA NVENC, Intel QSV, and VAAPI.

  • Configurable verification gates for duration tolerance, audio/subtitle retention, and required size reduction.

  • Hardware transcoding through NVIDIA NVENC, Intel QSV, and Intel/AMD VA-API, with per-encoder availability confirmed by a real test encode (not just inferred), and the encoder used shown per job (GPU/CPU) on the Queue.

  • GPU hardware decoding (QSV/VA-API) of the source as well as the encode, on by default, with automatic CPU-decode fallback for sources the GPU can't decode — so a large 4K encode no longer burns a CPU core just on software decode. Skipped for HDR→SDR tonemap jobs (the tonemap runs in software).

  • A "now encoding" hero panel with a live progress bar, fps/speed/ETA, and a live CPU/GPU usage graph while a job encodes (sampled with unprivileged reads only; no root or extra container capabilities). Click any job for a detail view showing the resolved encoder, the exact FFmpeg command, the verification report, and inline actions (retry, exclude, replace). The sidebar's Queue item throbs a GPU chip when work is hardware-accelerated or a snail when it's on the CPU, with a running-job count.

  • Optional service-activity pauses (Plex/Jellyfin/Emby), dry-run mode, configurable replacement/quarantine policy with a retention window, and library integrations (Plex/Jellyfin/Emby re-scan, Sonarr/Radarr import-aware exclusions, notifications, config-and-secrets backup/import).

Still planned (see the roadmap and maintained hardware validation matrix): real-hardware validation for AMD VA-API. Intel QSV has been tested on real hardware for both encoding and decoding.

Before you start

  • Docker Engine with the Compose plugin.
  • Read and write access to the media folders you mount into the container.
  • One host storage root mounted at /data, with media, work, and quarantine beneath it, if you want atomic replacement moves.
  • A backup of media that matters to you. Quarantine and rollback are useful, but they are not a backup strategy.

Quick start (Docker)

The image is published to GHCR on every push to dev:

mkdir -p ./optimisarr-config /path/to/storage/{media,.optimisarr/work,.optimisarr/trash}
sudo chown -R 1000:1000 ./optimisarr-config /path/to/storage
docker run -d --name optimisarr \
  -p 8787:8787 \
  -e PUID=1000 -e PGID=1000 -e TZ=Europe/London \
  -e OPTIMISARR_ADMIN_TOKEN='change-this-long-random-token' \
  -e OPTIMISARR_WORK_DIR=/data/.optimisarr/work \
  -e OPTIMISARR_TRASH_DIR=/data/.optimisarr/trash \
  -v ./optimisarr-config:/config \
  -v /path/to/storage:/data \
  ghcr.io/jellman86/optimisarr:dev

Wait for readiness, then open the UI:

curl http://localhost:8787/api/ready

Open http://localhost:8787. A new database opens the resumable five-step setup, verifies the mounted paths, free space, filesystem/mount relationships, permissions, and media tools. Missing or inaccessible storage gets concrete Docker Compose, Unraid, TrueNAS, or local recovery steps and a real Re-test action. Setup lets you fully configure as many libraries as needed and starts in Dry-run mode. Completing setup never starts a scan or job; review each library’s Candidates, then scan and queue a small test set deliberately. Use Run setup again in the Settings header to revisit the guided checks without deleting existing configuration. Add libraries from /data/media; the hidden work and quarantine directories remain below the same container mount boundary. Compose examples are available for every supported runtime:

Keep media, work, and quarantine beneath one container mount boundary when possible so the replacement pipeline can use atomic moves; separate bind mounts require the verified cross-filesystem fallback. Do not publish 8787 directly to the internet; use an authenticated reverse proxy for remote access. Setting OPTIMISARR_ADMIN_TOKEN adds a built-in bearer-token backstop for the UI and API, but a reverse proxy remains the recommended public-access boundary.

Hardware acceleration (GPU)

Transcoding runs through a bundled jellyfin-ffmpeg, which ships NVENC plus the Intel iHD driver and oneVPL runtime — so NVIDIA, Intel (incl. iGPUs like the N100), and AMD GPUs work without installing host driver packages. The encoder is picked by the global encoder mode (Settings → Auto by default); the Tools page shows what each GPU actually supports (availability is confirmed by a real test encode), and each Queue job shows whether it ran on the GPU or CPU. Perceptual quality measurement uses a separate, pinned static FFmpeg with libvmaf; the Tools page reports that optional capability independently. An optional OPTIMISARR_FFMPEG_VMAF_CUDA binary enables NVIDIA libvmaf_cuda when the build and runtime GPU support it; QSV/VA-API can offload SDR decoding while scoring remains on the CPU, and every hardware failure retries in software. VMAF verification is off by default for video re-encodes and skipped for remuxes; enable it per library under Libraries → Configure when the safeguard is worth the cost. Model choice and measurement preparation are automatic: HDTV/4K selection, reference-resolution bicubic scaling, timestamp/timebase and colour-range alignment, and like-for-like HDR→SDR reference tone-mapping require no libvmaf expertise. Optional early/middle/late sample scoring and 1–10 frame subsampling reduce runtime; every-frame scoring remains the safest default. VMAF-only failures get one encoder-aware higher-quality retry, and the report records the effective quality and sampling context.

When a hardware encoder is in use the source is hardware-decoded on the GPU too (Settings → Hardware decoding, on by default), so transcode frames stay on-device where the encoder supports it. If the GPU can't decode a particular source, the job automatically retries with software decode rather than failing. The Queue detail view shows a live CPU/GPU usage graph while a job runs — GPU stats are read without any elevated privileges (per-process DRM fdinfo for Intel/AMD, nvidia-smi for NVIDIA), so no extra container capability or compose change is needed; hosts where no unprivileged source applies simply show "GPU stats unavailable".

  • NVIDIA (NVENC): install the NVIDIA Container Toolkit on the host and run with --gpus all. You must also set NVIDIA_DRIVER_CAPABILITIES=compute,video,utility — without the video capability the NVENC library isn't injected and encoding fails with Cannot load libnvidia-encode.so.1 even though nvidia-smi works.

  • Intel (QSV / VA-API) and AMD (VA-API): map the render node and add the container to the host's render group:

    docker run -d --name optimisarr \
      --device /dev/dri:/dev/dri \
      --group-add "$(getent group render | cut -d: -f3)" \
      ... ghcr.io/jellman86/optimisarr:dev
    

Use the matching Compose example: NVIDIA NVENC, Intel QSV, or Intel/AMD VA-API. A CPU-only file is also provided.

Development

Standards and commands live in CLAUDE.md. In short:

dotnet build Optimisarr.slnx      # backend
dotnet test  Optimisarr.slnx      # tests
cd web && npm run check           # frontend type/lint check
cd web && npm run dev             # frontend dev server (proxies /api to :8787)

License

Optimisarr is licensed under the GNU General Public License v3.0. The published Docker image also bundles GPL-licensed FFmpeg distributions (jellyfin-ffmpeg and static-ffmpeg), which remain under their own licenses.

Project references

Install Optimisarr on Unraid in a few clicks.

Find Optimisarr in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for Optimisarr Review the template variables and paths Click Install

Related apps

Details

Repository
ghcr.io/jellman86/optimisarr:latest
Last Updated2026-07-17
First Seen2026-07-13

Runtime arguments

Web UI
http://[IP]:[PORT:8787]/
Network
bridge
Shell
bash
Privileged
false

Template configuration

WebUI PortPorttcp

Host port for the Optimisarr web interface (container listens on 8787).

Target
8787
Default
8787
Value
8787
ConfigPathrw

Persistent application state: SQLite database and configuration. Keep on fast storage.

Target
/config
Default
/mnt/user/appdata/optimisarr
Value
/mnt/user/appdata/optimisarr
Storage rootPathrw

One read-write root for your media, temporary output, and quarantine. Keeping them below one container mapping preserves atomic moves.

Target
/data
Default
/mnt/user/media
Value
/mnt/user/media
Work directoryVariable

Temporary transcode output inside the storage root. A separate fast-scratch mount requires the verified cross-filesystem fallback.

Target
OPTIMISARR_WORK_DIR
Default
/data/.optimisarr/work
Value
/data/.optimisarr/work
Quarantine directoryVariable

Rollback originals inside the storage root so replacements can use atomic moves.

Target
OPTIMISARR_TRASH_DIR
Default
/data/.optimisarr/trash
Value
/data/.optimisarr/trash
Admin TokenVariable

Optional. When set, the administrative API and UI require this bearer token. Leave blank to rely on your network/reverse-proxy for access control.

Target
OPTIMISARR_ADMIN_TOKEN
Timezone (TZ)Variable

Container timezone, e.g. Europe/London.

Target
TZ
Default
Europe/London
Value
Europe/London
PUIDVariable

User ID the app runs as (Unraid 'nobody' is 99). Files it creates use this owner.

Default
99
Value
99
PGIDVariable

Group ID the app runs as (Unraid 'users' is 100).

Default
100
Value
100
UMASKVariable

Permissions mask for files Optimisarr creates.

Default
002
Value
002
Intel/AMD GPU (/dev/dri)Device

Optional. Map the render node for Intel QSV/VA-API or AMD VA-API hardware transcoding. Remove if the host has no /dev/dri. For NVIDIA NVENC, add '--runtime=nvidia' and the NVIDIA_* variables via Extra Parameters instead (see the setup guide).

Target
/dev/dri
Default
/dev/dri
Value
/dev/dri