Skip to content

OPvault/convertarr

Convertarr

Convertarr

The missing *arr for your media server. Convertarr plugs into Sonarr and Radarr, ffprobes every file, and pre-encodes anything Jellyfin or Plex would otherwise have to transcode at playback — so streaming stays direct-play. Subtitles, attachments, chapters, and matching audio tracks are stream-copied bit-for-bit; only the offending streams get re-encoded.

Features

  • Sonarr + Radarr integration — point at your existing instances, browse the library with codec/format filters and global search, click rescan, watch the queue fill.
  • Visual workflow editor — build conversion rules on a drag-and-drop node canvas. Conditions on source codec, container, resolution, or audio select which files match; the workflow's video + audio targets drive the encode. No workflows defined = rescan is a no-op until you create one.
  • Triggers — feed a workflow manually (the Rescan button) or on a schedule with a Cron trigger that walks your library paths and re-ingests matched files automatically.
  • Stream actions — beyond codec conversion, a workflow can rename subtitle tracks to clean, canonical titles (SDH / Forced / Signs & Songs detection) and enforce a per-branch Time Limit circuit-breaker.
  • Hardware acceleration — auto-detects NVENC (NVIDIA), VAAPI (Intel/AMD), QSV (Intel), AMF (AMD), or falls back to libx265 (CPU). Full-GPU pipeline keeps frames in VRAM end-to-end where supported.
  • Multi-node — pair a second Convertarr instance as a worker with a short, confirm-on-screen handshake. The host owns the queue; workers pull jobs over HTTP and run them on their own hardware. Each worker reports its own concurrency cap and encoder.
  • Live dashboard — running jobs show progress, ETA, fps, speed, and an AV1 → HEVC codec chip so you can see exactly what's being transformed.
  • File indexer — a background ffprobe cache (Settings → System → Indexer) keeps library filters and cron triggers fast without re-probing on every request.
  • History + statistics/system/statistics charts codec, container, and resolution distribution across your library; /system/about shows version and uptime.
  • Backup / restore — export every user-editable setting (instances, path mappings, workflows, saved filters) as JSON and import it on a fresh install. Instance-identity secrets (app API key, session secret, password hash, pairing tokens) are redacted and never overwritten on import.
  • Secure by default — a fresh install forces a /setup admin account before it serves anything; the machine-to-machine API is always API-key gated regardless of UI auth mode.

Quick start (Docker)

Grab the sample docker-compose.yml (NVIDIA-by-default; VAAPI / CPU notes inline at the bottom of the file), drop it next to a config/ folder, and:

docker compose up -d

Adjust:

  • Volumes — bind your media at the same path Sonarr/Radarr uses internally. Convertarr receives the *arr-relative path and opens it directly; mismatched paths force you to set up Path Mappings on every *arr instance.
  • PUID / PGID — set to the user that owns your media bind-mounts. 0/0 runs the container as root if you can't or won't chown.
  • GPU — see "Hardware acceleration" below.

Open http://localhost:6565. On first run you'll be sent to /setup to create an admin username + password — Convertarr won't serve protected pages until you do. Then add your Sonarr/Radarr instances under Settings → Sonarr / Radarr, define a workflow under Settings → Workflows, and click Rescan on a series or movie.

Prebuilt images are published to https://github.com/OPvault/convertarr/pkgs/container/convertarr on every push to main and every v* tag. :latest follows the newest build on main; pin a specific release with :1.1.0 (or the sliding :1 / :1.1 tags) for reproducible deploys.

Quick start (bare metal)

For development or environments where Docker isn't available. Requires Python 3.12+, ffmpeg, and ffprobe.

git clone https://github.com/OPvault/convertarr
cd convertarr
./run.sh

run.sh creates the venv on first run, installs the package in editable mode, and launches Convertarr on 0.0.0.0:6565. Pass --no-reload for production-style runs. As with Docker, first run lands on /setup.

State (DB, logs, runtime settings) lives in data/ next to the source tree. Override with CONVERTARR_DATA_DIR=/some/path.

Workflows

A workflow is a "when the source matches these conditions, target these codecs (and run these actions)" rule. Workflows are the only path to a conversion — Convertarr runs nothing until at least one is defined. Build them on the node canvas under Settings → Workflows.

Anatomy of a workflow

You assemble a workflow from nodes on the editor canvas:

  • TriggerManual (the Rescan button, the implicit default) and/or Cron (a recurring filesystem walk of configured library paths). A workflow with no cron trigger only runs when you rescan.
  • Conditions (the Match node) — zero or more clauses ANDed/ORed together. An empty list is a catch-all.
  • Codec targetsVideo Codec (copy, h264, hevc, av1) and Audio Codec (copy, aac, ac3, eac3, opus, flac).
  • Actions — optional extra steps: Rename Subtitles (rewrite messy subtitle track titles to canonical names) and Time Limit (a per-branch wall-clock circuit-breaker).
  • Priority — lower number wins. The first enabled workflow whose conditions match is chosen and the rest are skipped. Within a workflow, branches are evaluated top to bottom and the first matching branch wins.

A workflow can hold multiple branches (each its own condition set + targets + actions), so one workflow can, say, send AV1 to HEVC on one branch and FLAC to AAC on another.

Condition fields

Field Type Source Notes
video_codec string primary video stream's codec_name attached_pic (cover art) is ignored
container string ffprobe format_name, normalised matroskamkv, mov,mp4,m4amp4
resolution number primary video stream height e.g. 1080, 2160
audio_codec string set of every audio stream's codec is matches when any audio track is that codec
audio_channels number max channels across audio streams a 5.1 + stereo file evaluates to 6

Operators

  • is / is not — exact match. Multi-value: is matches if any value matches; is not requires none of them match.
  • contains / does not contain — substring (strings only). Useful for catching variants like mpeg2video.
  • is greater than / is less than — numeric (height, channels).

Clauses are joined with and (default) or or. Standard precedence — A and B or C and D becomes (A and B) or (C and D). A workflow branch matches when any AND-group passes.

What runs after a match

The matched branch's video / audio targets become the per-file plan. Convertarr then walks every stream and decides:

  • Video (non-cover-art): re-encode if the source codec doesn't equal the target, copy otherwise. h264 / avc / x264 are treated as the same codec — same for hevc / h265 / x265 — so a "target hevc" rule on an already-hevc file is a no-op even if the source codec is named x265.
  • Audio: re-encode the streams that aren't the target codec; the rest are stream-copied.
  • Subtitles: copied bit-for-bit — unless the branch has a Rename Subtitles action, which rewrites their titles in place.
  • Attachments (fonts), chapters, data: always copied.
  • Cover art / poster jpegs (dispositioned attached_pic): always copied.

If every stream ends up copy (and there's no subtitle rename to do), no Job is queued — the rescan is treated as "nothing to do" rather than firing a remux.

Example (export shape)

A real-world catch-all that normalises everything into HEVC video + AAC audio. This is the branches shape you'd see in a /system/backup export:

{
  "name": "Normalize to HEVC + AAC",
  "enabled": true,
  "priority": 100,
  "branches": [
    {
      "conditions": [
        { "field": "video_codec", "op": "equal",
          "value": ["h264", "av1", "vp9", "mpeg4", "mpeg2video", "vc1"],
          "connector": "and" },
        { "field": "audio_codec", "op": "equal",
          "value": ["flac"],
          "connector": "or" }
      ],
      "target_video_codec": "hevc",
      "target_audio_codec": "aac",
      "actions": []
    }
  ],
  "triggers": []
}

How the branch reads: the or connector on the second clause splits the conditions into two groups, so it matches when either is true:

  • Video group — primary video codec is one of h264, av1, vp9, mpeg4, mpeg2video, or vc1 (i.e. anything that's not already HEVC).
  • Audio group — any audio track is FLAC.

Anything matching either group gets re-encoded to HEVC video + AAC audio; tracks that already match the target are stream-copied (so a file with HEVC video but a FLAC track only re-encodes the FLAC). Matching files that are already HEVC + AAC across the board produce no work.

You normally build this clause-by-clause on the editor canvas; the JSON above is what's stored in the DB and exported. (Older flat exports — conditions / target_video_codec / target_audio_codec at the top level — still import; they're wrapped into a single branch.)

Cron triggers

Add a Cron trigger node to run a workflow on a schedule instead of (or in addition to) the Rescan button. You give it a cron expression and one or more library paths; on each fire Convertarr reads its file index for those paths and re-ingests matched files through the workflow's branches. Trigger paths are contained to your configured library roots — a workflow can't point the scheduler at arbitrary parts of the filesystem.

Files discovered by a cron trigger that don't map to any known Sonarr/Radarr entry land in Activity → Unlinked (operator-facing, never auto-queued) rather than the encode queue.

Rescan with a specific workflow

The Rescan button on a series/movie page lets you pick a workflow from a dropdown. The chosen workflow is still evaluated against the file's conditions — picking "Convert AV1 to HEVC" on an HEVC file won't fire it. This way you can re-trigger a specific rule without rearranging priorities.

Hardware acceleration

The image bundles ffmpeg with libx265 (CPU) plus VAAPI / NVENC / QSV support. The host needs to expose its GPU into the container:

GPU Compose
NVIDIA deploy.resources.reservations.devices block with capabilities: [gpu, compute, utility, video]. Requires nvidia-container-toolkit on the host.
Intel / AMD VAAPI devices: ["/dev/dri:/dev/dri"] + group_add: ["video", "render"]
CPU only nothing — libx265 always works.

Convertarr auto-detects the best available encoder at startup. Override per-node from Settings → Nodes if it picks the wrong one.

Note: AV1 NVDEC requires Ada Lovelace (RTX 4060+); on older NVIDIA cards Convertarr automatically SW-decodes AV1 sources. 10-bit H.264 (Hi10P) is also SW-decoded on VAAPI/QSV because most implementations don't support it.

Multi-node setup

Run Convertarr on a second machine the same way (Docker or bare-metal) and complete its /setup. Then pair it with a short, Wii-U-style confirmation handshake:

  1. On the host's Settings → Nodes page, enter the worker's address and the worker's API key (both under that worker's Settings → General). Click Begin pairing.
  2. The worker shows four coloured shapes on its own Settings → Nodes screen.
  3. Tap that same sequence into the host's confirm page.

On a match, the host issues the worker a scoped, revocable per-node token (it never ships its own master API key), the worker switches into worker-mode within a few seconds, and it starts pulling jobs. The four-shape code is the out-of-band human check — it never crosses the API, so knowing the worker's API key alone isn't enough to pair.

Each worker decides its own Max concurrent jobs (Settings → General on that machine; 0 = host-only / paused). Workers configure their own Sonarr/Radarr Path Mappings, so the host can dispatch *arr-relative paths and the worker resolves them locally — useful when host and worker have different mount layouts. delete-originals is a worker-local policy: the host can't make a worker delete files its own settings wouldn't.

Disconnect with the Disconnect from host button on the worker, or Unpair from the host's Nodes page.

Configuration reference

All runtime config is editable from the web UI under Settings:

  • General — auth (forms is the default; none requires an explicit opt-in env var, see below), API key, max concurrent jobs (this node), delete-originals toggle, encoder override.
  • Sonarr / Radarr — instances + path mappings.
  • Workflows — the node-canvas editor for conversion rules + triggers.
  • Nodes — pair / unpair workers, view their encoder + version.
  • System — Logs, Statistics, Indexer (file-index status + manual sweep/reindex), Backup, About.

A handful of immutable settings live in env vars (prefix CONVERTARR_), useful for headless setups:

  • CONVERTARR_DATA_DIR — where the DB / logs / settings live (/config in Docker).
  • CONVERTARR_DB_URL — SQLAlchemy DB URL override.
  • CONVERTARR_HOST_URL_HINT — overrides the host URL sent to workers when pairing.
  • CONVERTARR_ALLOW_NO_AUTH=1 — the only way to honour a stored auth_method = none. Without it, a stored none is treated as forms auth, so a default install on 0.0.0.0 is never anonymous. Set this only on a trusted, isolated network.

Status

Convertarr is in active development (current version 1.1.0). The default flow is non-destructive — failed/cancelled encodes never touch the original — but always confirm with a test library first. Originals are moved to a sibling .convertarr-backup/ folder when delete-originals is off.

Source: https://github.com/OPvault/convertarr · Issues: https://github.com/OPvault/convertarr/issues · Security: see SECURITY.md

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors