No description
  • Python 88.8%
  • HTML 10.1%
  • Shell 0.7%
  • Dockerfile 0.4%
Find a file
Tobias Hertel dbad8801e9
All checks were successful
CI / test (push) Successful in 25s
Build native executables / linux-amd64 (push) Successful in 36s
Build native executables / windows-amd64 (push) Successful in 1m7s
Build native executables / linux-arm64 (push) Successful in 3m54s
Build native executables / release (push) Has been skipped
Build and push container image / build-and-push (push) Successful in 3m21s
fix: sanitize profile labels in output paths
2026-11-11 10:06:06 +01:00
.forgejo/workflows Delete hardware.yml 2026-11-08 11:27:36 +01:00
app fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
config feat: accelerate bitmap subtitle OCR 2026-10-27 19:37:06 +01:00
docs Unify the v0.32 application shell 2026-10-21 10:18:03 +02:00
scripts test: add hardware integration gates 2026-09-19 01:45:18 +02:00
tests fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
.dockerignore simplified config dirs 2026-08-16 19:39:53 +02:00
.env.example feat: distribute jobs by worker profiles 2026-09-14 11:34:51 +02:00
.env.macos.example docs: publish Optimizarr 0.10 deployment model 2026-09-12 20:10:00 +02:00
.gitattributes Initial commit 2026-08-16 14:35:45 +02:00
.gitignore feat: add portable backup and restore 2026-09-19 01:04:45 +02:00
CHANGELOG.md fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
compose.dev.yml fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
compose.nvidia.yml docs: publish Optimizarr 0.10 deployment model 2026-09-12 20:10:00 +02:00
compose.qsv.yml docs: publish Optimizarr 0.10 deployment model 2026-09-12 20:10:00 +02:00
compose.vaapi.yml Add AMD VAAPI worker support 2026-10-04 16:07:48 +02:00
compose.worker-http.yml fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
compose.worker.yml fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
compose.yml fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
Dockerfile feat: add image subtitle OCR pipeline 2026-10-26 22:31:17 +01:00
pyproject.toml fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00
README.md fix: sanitize profile labels in output paths 2026-11-11 10:06:06 +01:00

Optimizarr v0.39.1

Optimizarr erzeugt über eine lease-basierte Multi-Worker-Queue optimierte Medienableitungen für Radarr-/Sonarr-Bibliotheken. Eingabemedien werden ausschließlich read-only eingebunden. Ein Worker encodiert zuerst lokal, lädt anschließend in eine versteckte Datei im Zielverzeichnis und die API veröffentlicht diese erst nach gültiger Lease per atomarem Rename.

Schnellstart

cp config/config.example.yml config/config.yml
docker compose -f compose.yml -f compose.qsv.yml up -d --build

Für einen Linux-Worker mit AMD-GPU wird stattdessen die VAAPI-Erweiterung verwendet:

docker compose -f compose.yml -f compose.vaapi.yml up -d --build

Das Runtime-Image enthält dafür Mesa VAAPI/Vulkan (radeonsi). DRM_RENDER_DEVICE kann den standardmäßigen Render-Knoten /dev/dri/renderD128 überschreiben. QSV_DEVICE bleibt als abwärtskompatibler Fallback für bestehende Intel-Installationen erhalten.

Das Dashboard läuft standardmäßig auf http://localhost:8097. Beim ersten Start liegt der einmalige Admin-Code unter config/runtime/setup.token. Einstellungen, Profile, Regeln, Sprachfilter und Worker werden danach in der Administration verwaltet.

Der lokale Worker erhält automatisch ein Token in einem ausdrücklich deklarierten worker-auth-Volume. Die Anwendungseinstellungen bleiben vollständig unter /config; es gibt keinen zusätzlichen /data-Mount. Redis wird im Standard-Compose nicht am Host veröffentlicht.

Remote-Worker unterscheiden einen bestätigten Lease-Verlust von einer vorübergehend nicht erreichbaren API. Während einer Netzwerk- oder VPN-Unterbrechung laufen ausschließlich worker-lokale Transcodes und Prüfungen weiter; Upload und atomarer Publish warten auf eine wieder erreichbare API und eine bestätigte Lease. queue.worker_outage_grace_seconds hält den Job standardmäßig 15 Minuten exklusiv, bevor ein tatsächlich ausgefallener Worker ersetzt werden darf.

Architektur

Radarr / Sonarr ──API/Webhook──> Optimizarr API ──> SQLite-Katalog
                               │       │
                               │       └──────> Redis (Queue/Leases)
                               ▲                    │
                          HTTPS/API                 │ atomarer Commit
                               │                    ▼
                         Worker ─────upload────> /optimized
                           │
                     lokales /work

Worker kennen weder Redis-Zugangsdaten noch den Settings-Schlüssel oder Integrations-Secrets. Sie benötigen nur:

  • OPTIMIZARR_API_URL
  • eine read-only Token-Datei über OPTIMIZARR_WORKER_TOKEN_FILE
  • lokales /work
  • im Standardmodus read-only Quellmounts und den gemeinsamen Output-Mount; im HTTP-Modus entfallen diese Medienmounts

Für einen entfernten Worker zuerst in der Administration einen Worker anlegen und das einmalig angezeigte Token in eine Datei schreiben. compose.worker.yml nutzt gemeinsame Medienpfade; compose.worker-http.yml benötigt nur OPTIMIZARR_WORKER_TOKEN_PATH, OPTIMIZARR_WORK_PATH und OPTIMIZARR_API_URL. Unverschlüsseltes HTTP ist nur für ein abgeschottetes LAN geeignet; über Netbird oder andere Netze wird HTTPS empfohlen.

Unter Administration → Worker werden Betriebsmodus, Profilfreigaben, Beschleuniger, Kapazitäten, Arbeitsverzeichnis und beliebig viele canonical→lokal-Pfadzuordnungen je Worker zentral gespeichert. Zusätzlich bestimmt Metadaten prüfen und Varianten planen, welche Worker noch ungeplante Arr-Quellen öffnen, mit ffprobe prüfen und anhand der Regeln in konkrete Varianten aufteilen dürfen. Bilduntertitel lokal extrahieren weist die vorbereitende PGS-/VobSub-Extraktion gezielt einem Shared-Storage-Worker mit direktem Medienzugriff zu. Standardmäßig sind beide Rollen nur für local-worker aktiv. Der längste passende canonical Präfix gewinnt. Der Worker prüft alle konfigurierten Medienwurzeln, das Ausgabeziel und das lokale Arbeitsverzeichnis bei jedem Heartbeat. Solange eine Konfigurationsrevision noch nicht bestätigt wurde oder benötigte Pfade nicht les- beziehungsweise beschreibbar sind, claimt dieser Worker keine betroffenen Jobs; das verbraucht keinen Medien-Retry. Drain lässt laufende Jobs sicher fertig werden und verhindert neue Claims.

Jobs mit mehreren Zielprofilen werden profilbasiert verteilt. Ein Worker übernimmt in einem Claim alle noch fehlenden Profile, die für ihn freigegeben sind. Kompatible SDR-Ziele teilen sich Decode und HDR-Tone-Mapping in einem Multi-Output-Graph und werden erst danach unabhängig skaliert und encodiert. HDR-Preserve-Ausgaben bleiben wegen ihrer Metadatenverarbeitung getrennt. Scheitert der gemeinsame Graph technisch, fällt der Job einmal auf den seriellen Einzelpfad zurück. Bereits veröffentlichte Profile werden nicht erneut berechnet.

max_transcodes begrenzt parallele Quelljobs. max_nvenc_sessions reserviert davon unabhängig die tatsächlich gleichzeitig verwendeten NVENC-Encoder; ein Multi-Output-Job kann mehrere Sitzungen belegen und wird bei Bedarf in kleinere Gruppen geteilt. Transcode- und Aktivlimits werden zusätzlich atomar durch die API pro Worker-ID erzwungen. Versehentlich doppelt gestartete Prozesse mit demselben Token können das Limit daher nicht mehr überschreiten und werden in der Administration als mehrere Instanzen markiert.

Jeder Worker kann einen Wochenzeitplan mit IANA-Zeitzone und separaten Zeitfenstern pro Wochentag erhalten. Zeitfenster dürfen Mitternacht überschreiten. Außerhalb eines Fensters gilt automatisch Drain: Neue Jobs werden nicht geclaimt, laufende Transcodes und Veröffentlichungen werden sicher abgeschlossen. Beim nächsten Zeitfenster nimmt der Worker ohne Neustart wieder Arbeit an.

Pfadzuordnungen, Beschleunigerpräferenzen, Arbeitsverzeichnis und Kapazitätsgrenzen werden per Heartbeat übernommen und gelten für danach geclaimte Jobs. Laufende Jobs behalten ihren sicheren Konfigurations-Snapshot. Docker-Volumes und Geräte wie /dev/dri oder /dev/nvidia0 kann die API nicht erzeugen: Sie müssen weiterhin in Compose vorhanden sein. Der Hardware-Preflight zeigt getrennte Codec-Matrizen für Decoding und Encoding sowie echte QSV-, VAAPI-, NVENC- und VideoToolbox-Testencodes. Kann ein ausgewählter Beschleuniger den Quellcodec, etwa AV1, nicht dekodieren, bleibt dessen Hardware-Encoder nutzbar und Optimizarr wechselt für Decode und Filter automatisch auf Software.

Auf nativem macOS verwendet der Einzelprofilpfad VideoToolbox-Decoding und scale_vt, sofern Quellcodec, FFmpeg-Build und Hardware dies unterstützen. Für HDR→SDR kann ein erfolgreich geprüfter libplacebo/Vulkan- oder OpenCL-Pfad genutzt werden; andernfalls bleibt der validierte CPU-Fallback verfügbar. Multi-Output-Jobs teilen weiterhin einen Decode-/Tonemap-Graph, um das teure Tonemapping nur einmal auszuführen. Der Dashboard-Pfad zeigt diese Entscheidungen einschließlich Fallback vollständig an.

OPTIMIZARR_WORKER_API_TIMEOUT_SECONDS steuert den normalen API-Timeout (Standard: 15 Sekunden). Fortschrittsmeldungen verwenden mit OPTIMIZARR_WORKER_PROGRESS_TIMEOUT_SECONDS bewusst einen kürzeren Timeout von 2 Sekunden, damit ein unterbrochener Tunnel den FFmpeg-Ausgabepuffer nicht ausbremst.

Native Worker-Binaries

Der Forgejo-Workflow native.yml baut einzelne Optimizarr-Executables für Linux amd64, Linux ARM64 und Windows amd64. Bei normalen Builds stehen sie 30 Tage als Workflow-Artefakte bereit; ein passender v*-Tag veröffentlicht sie zusätzlich mitsamt SHA-256-Prüfsummen als Forgejo-Release. Der Git-Tag muss dabei exakt zur Projektversion passen.

Die Runner-Labels und Voraussetzungen sind:

  • pyinstaller-linux-amd64: natives amd64-Linux mit Bash, Python 3.11+, file, sha256sum und Node-Unterstützung für Forgejo-Actions.
  • pyinstaller-linux-arm64: durch QEMU/binfmt ausgeführtes ARM64-Linux mit denselben Werkzeugen; platform.machine() muss innerhalb des Jobs aarch64 oder arm64 melden. PyInstaller kompiliert nicht quer – der Runner muss den gesamten Job daher wirklich im ARM64-Userspace ausführen.
  • pyinstaller-windows-amd64: Linux mit Bash, Wine/Wine64, winepath, file, sha256sum und einem 64-Bit-Windows-Python im Wine-Pfad. Falls python.exe dort nicht direkt auflösbar ist, muss WINDOWS_PYTHON, beispielsweise auf C:\\Python313\\python.exe, gesetzt werden.

Die Executables enthalten Optimizarr und seine Python-Abhängigkeiten. ffmpeg, ffprobe, dovi_tool und hdr10plus_tool bleiben plattformspezifische Laufzeitabhängigkeiten und müssen auf dem Worker im PATH vorhanden sein. Fehlt seconv bei einem nativen Worker vollständig, lädt Optimizarr einmalig das passende Asset des neuesten stabilen Subtitle-Edit-Releases in den Unterordner seconv neben dem Optimizarr-Executable. Der von GitHub veröffentlichte SHA-256-Digest wird vor der atomaren Installation geprüft. Ein explizites SECONV_PATH oder ein bereits vorhandener Zielordner wird niemals überschrieben; mit OPTIMIZARR_SECONV_AUTO_DOWNLOAD=false lässt sich der Bootstrap abschalten und mit SECONV_INSTALL_DIR an einen beschreibbaren Ort umleiten. Tesseract/PaddleOCR werden von seconv als externe Engines erkannt; unter macOS kann das eingebaute Apple Vision ohne weitere OCR-Engine genutzt werden. Gestartet wird beispielsweise mit optimizarr-0.39.1-linux-amd64 worker; nach einem direkten Linux-Download muss gegebenenfalls zuerst das Ausführungsbit gesetzt werden.

Medienindex und Bibliotheksüberwachung

Seit v0.31 verwaltet Optimizarr Filme, Serien, Episoden, Originalgenerationen und erzeugte Varianten in einem langlebigen SQLite-Katalog unter /config/runtime/catalog.db. Redis bleibt für Queue, Leases und Worker-Heartbeats zuständig. Ab v0.33 können Radarr und Sonarr der primäre Index sein: Optimizarr importiert Titel, stabile IDs, Dateipfade und die dort vorhandenen Metadaten ausschließlich über deren API. Erst wenn eine neue oder ersetzte Quelle tatsächlich geplant werden muss, öffnet ein freigegebener Metadaten-Worker genau diese Datei für den vollständigen Probe. Unter Filme, Serien, Wanted und Verlauf stehen eine katalogorientierte Oberfläche, Detailansichten aller Originalgenerationen und Varianten sowie eine Vorschau des gewünschten Zustands bereit.

Wird ein Original in Sonarr/Radarr ersetzt, entsteht eine neue Generation. Jobs der alten Generation dürfen danach nicht mehr veröffentlichen. Die bisherige optimierte Datei bleibt verfügbar, bis die neue Variante erfolgreich atomar veröffentlicht wurde; erst anschließend wird die alte Variante zunächst nach .retired verschoben und nach der konfigurierten Frist entfernt. Fehlende Originale und nicht mehr gewünschte Profile verwenden ebenfalls Schonfristen. Die automatische Bereinigung ist standardmäßig deaktiviert und jede zu entfernende Datei muss innerhalb des konfigurierten Optimized-Verzeichnisses liegen.

Mehrere Sonarr-/Radarr-Instanzen können denselben numerischen Medien-Identifier verwenden. Hinterlege am jeweiligen Webhook ?instance=uhd oder den Header X-Optimizarr-Instance: uhd; ohne Angabe bleibt die abwärtskompatible Instanz default aktiv.

Optimizarr führt den Zustand pro Originaldatei und Profil. Neu aktivierte oder durch eine Regel neu zugewiesene Profile werden für passende, bereits indexierte Medien ergänzt, ohne aktuelle Profile erneut zu encodieren. Wartende Jobs werden atomar erweitert; läuft ein Encode bereits, wird anschließend ausschließlich das hinzugekommene Profil verarbeitet. Beim Deaktivieren werden noch nicht begonnene Profilanteile aus wartenden Jobs entfernt; technische Umbenennungen migrieren Queue, Historie, Medienindex und Worker-Freigaben. Eine Umbenennung oder Löschung mit aktivem Encode wird abgelehnt, bis der betroffene Job beendet oder der Worker geleert wurde. Profiländerungen, fehlende Outputs, Fehler und abgebrochene Läufe werden sichtbar markiert und können in der Administration gezielt pro Datei und Profil neu gestartet werden.

Ist unter Einstellungen → Radarr- und Sonarr-Index mindestens eine aktive Instanz eingetragen und Arr als primärer Index aktiviert, installiert Optimizarr keine Dateisystem-Watches und startet keine geplanten Vollscans. Webhooks melden Änderungen sofort; ein standardmäßig 15-minütiger API-Abgleich erkennt verpasste Events, ohne Medienverzeichnisse zu traversieren. Wiederholte Importe erzeugen keine doppelten Jobs. API-Schlüssel werden verschlüsselt unter /config gespeichert.

Die optionale direkte Bibliotheksüberwachung bleibt als Fallback für Bibliotheken ohne Arr verfügbar. Sie arbeitet ereignisbasiert und ist zunächst deaktiviert. Neue oder verschobene Dateien werden einzeln vorgemerkt, erst nach stabiler Größe und Änderungszeit geprüft und anschließend durch dieselbe Index- und Duplikaterkennung wie ein Bootstrap geführt. Im Hybridmodus ergänzt ein konfigurierbarer Sicherheitsabgleich die Events; reconciliation_interval_hours: 0 beziehungsweise der Modus events verhindert automatische Vollscans vollständig. polling erhält den bisherigen Intervallbetrieb.

Für ein Unraid-Array bleibt event_recursive: false empfohlen: Beim API-Start werden dann nur die Bibliothekswurzeln beobachtet und neu angelegte Verzeichnisse dynamisch ergänzt, ohne zuerst den gesamten Verzeichnisbaum zu durchlaufen. Neue Dateien in bereits vor dem API-Start vorhandenen tiefen Serienordnern benötigen in dieser Betriebsart einen Sonarr-/Radarr-Webhook oder den seltenen Sicherheitsabgleich. event_recursive: true deckt diese Fälle vollständig über Dateisystem-Events ab, installiert dafür beim Start rekursive Watches und kann dadurch schlafende Datenträger wecken. Status, wartende Events und Fehler sind unter Administration → Bibliotheksüberwachung sichtbar; der manuelle Vollscan bleibt jederzeit verfügbar. Fehlgeschlagene Jobs, fehlende Originale und extern gelöschte Outputs werden nicht automatisch erneut verarbeitet oder gelöscht.

Unter Administration → Einstellungen → Dateinamenregeln können Filme und Serien mit getrennten, geordneten Regex-Ersetzungen normalisiert werden. Die Regeln bearbeiten ausschließlich den Original-Dateinamen ohne Erweiterung; Optimizarr ergänzt anschließend weiterhin den Profilnamen und den Zielcontainer und lehnt unsichere Pfadbestandteile ab.

Worker übernehmen zentrale Profilfreigaben, Pfadzuordnungen, Beschleuniger, Arbeitsverzeichnis und Kapazitätsgrenzen mit dem nächsten Heartbeat ohne Neustart. Änderungen gelten für neue Jobs; laufende Jobs behalten ihren beim Claim bestätigten Konfigurationsstand.

Worker ohne gemeinsame Medienmounts können pro Worker auf den resumierbaren HTTP-Transport umgestellt und mit compose.worker-http.yml gestartet werden. Quellen werden in geprüften Byte-Ranges lokal zwischengespeichert, Outputs sequenziell mit Chunk- und Gesamt-SHA-256 hochgeladen und erst nach einer erneuten Lease-Prüfung atomar veröffentlicht. Unterbrochene Übertragungen werden anhand des serverseitigen Offsets fortgesetzt. Details und Reverse-Proxy-Anforderungen stehen in docs/HTTP_MEDIA_TRANSFER.md.

Die Administration ist in Bibliothek, Profile & Regeln, Worker, Einstellungen und System gegliedert. Im Medienindex kann ein Original neu geprüft oder ausschließlich aus dem Redis-Index entfernt werden. Unter System → Index-Wartung lassen sich fehlende Originale gesammelt vergessen oder der gesamte Index nach Eingabe von INDEX ZURÜCKSETZEN leeren. Keine dieser UI-Aktionen löscht Originale, erzeugte Derivate oder Jobhistorien. Ein vollständiger Reset ist während laufender Scans sowie wartender oder aktiver Jobs gesperrt; danach kann ein neuer Scan bestehende Derivate erneut erzeugen.

Bestehende Medien einlesen

Für Arr-Bibliotheken ist Administration → Bibliotheken → Arr-Index importieren der bevorzugte Erstimport. Er liest weder /media noch einzelne Mediendateien. Die daraus entstehenden ungeplanten Jobs werden ausschließlich von Workern mit aktivierter Metadatenplanung übernommen; erst dort folgen ffprobe, Regelauswertung, Variantenauswahl und Transcoding.

Der manuelle Datei-Scan kann weiterhin eine alphabetisch sortierte Vorschau für Filme, Serien oder beide Medientypen laden. Er ist nur als Fallback für Bibliotheken ohne Arr oder für Wartungszwecke gedacht und greift direkt auf die Medienpfade zu.

Der Kommandozeilenmodus python -m app bootstrap --dry-run --limit 5 bleibt für Wartungsarbeiten verfügbar.

Profile und HDR

Profile können H.264, HEVC oder AV1 ausgeben. AV1 wird je nach Worker über QSV, VAAPI, NVENC, VideoToolbox oder als CPU-Fallback über SVT-AV1, libaom beziehungsweise rav1e gewählt. Statisches HDR10 bleibt als 10-Bit-Ausgabe erhalten. AV1 kann Dolby Vision als Profil 10 über FFmpegs libsvtav1-Encoder erhalten, wenn die Quelle bereits ein Single-Layer-Profil 8/10 besitzt und nicht skaliert wird. Optimizarr prüft die Encoderoption auf jedem Worker und erzwingt für dieses Profil den Softwarepfad. Profil 5, Profil 7/FEL und skalierte Dolby-Vision-Ausgaben werden derzeit mit einer klaren Fehlermeldung abgelehnt. HDR10+ bleibt wegen der verfügbaren Metadaten-Werkzeuge auf MKV/HEVC beschränkt.

Bei HDR→SDR prüft jeder Worker echte libplacebo/Vulkan-, OpenCL- und VAAPI-Tonemap-Graphen. hdr.tonemap_acceleration: auto nutzt den ersten erfolgreichen GPU-Pfad; cpu erzwingt den bisherigen zscale/Hable-Pfad. Ein Filterfehler oder schwarze Stichproben verwerfen die Staging-Datei und wiederholen denselben Output einmal mit CPU-Tonemapping. NVIDIA-Worker verwenden für nicht tonemap-pflichtige Quellen zusätzlich CUDA-Decoding und scale_cuda, sofern Quellcodec und FFmpeg-Build dies unterstützen. Worker-, FFmpeg- und API-Version sowie die getesteten Tonemap-Pfade werden in der Administration angezeigt.

Die Standardprofile heißen:

  • 4k-hevc-hdr: HEVC Main10, 10 Mbit/s Ziel, 8–12 Mbit/s Begrenzung
  • 1080p-hevc-hdr: HEVC Main10, 6 Mbit/s Ziel, 5–8 Mbit/s Begrenzung
  • 1080p-h264-sdr
  • 720p-h264-sdr

Audio- und Untertitelsprachen lassen sich je Profil als ISO-639-Allowlist führen. Der optionale Modus Beste Hauptspur je Sprache priorisiert verlustfreie und objektbasierte Formate, Kanalzahl und Bitrate. Er kann die beste Originalspur behalten und daraus zusätzlich E-AC-3 5.1 mit standardmäßig 640 kbit/s sowie AAC Stereo mit 192 kbit/s erzeugen. Passende Spuren werden nicht dupliziert und Audio wird niemals hochgemischt. TrueHD/Atmos bleibt in der kopierten Originalspur erhalten; Kompatibilitätsspuren enthalten einen klassischen kanalbasierten Downmix. Kommentar- und Audiodeskriptionsspuren sind separat zuschaltbar. Freie Quelltitel werden bei jeder Ausgabe durch einheitliche Titel wie Dolby Digital 5.1, Dolby Digital Plus 5.1, Dolby TrueHD Atmos 7.1 oder AAC Stereo ersetzt. Atmos beziehungsweise DTS:X wird nur bei unverändert kopierten Spuren ausgewiesen.

Bildbasierte Untertitel (PGS, VobSub, DVB-Sub und XSUB) können je Profil mit subtitles.mode: ocr als SRT in die MKV-Ausgabe übernommen werden. Bereits textbasierte Spuren bleiben unverändert. Gleichwertige Textspuren ersetzen standardmäßig doppelte Bildspuren. Ein freier Transcoding-Worker reserviert zuerst einen passenden Job. Nur wenn dessen konkret zugewiesene Profile ein noch fehlendes OCR-Artefakt benötigen, erhält ein als Bilduntertitel lokal extrahieren markierter Shared-Storage-Worker eine separate Extraktions-Lease. Er liest die Originaldatei direkt und veröffentlicht ausschließlich die ausgewählten Bildspuren lease-geschützt unter /optimized/.optimizarr/subtitle-artifacts. Danach übernimmt der reservierte Transcoding-Worker den Job; geht er offline, verfällt die Reservierung und ein anderer kompatibler Worker kann das Artefakt verwenden. So fährt der Extractor die Bibliothek nicht unabhängig von freien Encoder-Slots hoch. Ohne verfügbares Artefakt bleibt die lokale Einmal-Extraktion als Sicherheits-Fallback erhalten. Die Erkennung läuft standardmäßig mit zwei, über ocr_parallelism auf eins bis vier begrenzbaren Prozessen. OCR wird pro Job und identischer Untertitelrichtlinie nur einmal ausgeführt und anschließend von kompatiblen Multi-Output-Profilen gemeinsam verwendet. Extraktion, aktive Sprachen, Spurfortschritt und Laufzeit erscheinen live im Jobstatus. ocr_engine: auto bevorzugt auf macOS Apple Vision und ansonsten Tesseract; ocr_fallback legt fest, ob eine einzelne fehlgeschlagene Spur im Original kopiert, entfernt oder der Job abgebrochen wird. Worker melden ihre tatsächlich verfügbaren Engines, sodass OCR-Jobs nur von kompatiblen Workern geclaimt werden. Die Container-Images enthalten seconv 5.3 sowie deutsche und englische Tesseract-Sprachdaten.

Ohne audio.selection: best_per_language bleiben Auswahl und Codec-Verarbeitung unverändert; lediglich die Spurtitel werden ebenfalls standardisiert. Der Bootstrap-Preflight zeigt den geplanten Audiotrack-Aufbau und berücksichtigt ihn ebenso wie die Worker-Speicherreservierung. Nach dem Encode werden Codec, Sprache und Kanalzahl jeder geplanten Spur vor dem Publish validiert.

Das Image enthält die fest gepinnten quietvoid-Werkzeuge dovi_tool 2.3.4 und hdr10plus_tool 1.7.2. Für MKV/HEVC-Profile kann Dolby Vision beziehungsweise HDR10+ auf preserve oder drop gestellt werden. Die Erhaltung ist strikt: fehlt ein Werkzeug, stimmt die Frame-Timeline nicht oder lässt sich das Ergebnis nicht erneut validieren, schlägt der Job sichtbar fehl. Profil 7 wird zu einer Single-Layer-P8.1-RPU konvertiert, Profil 5 zu P8.1 und P8.1 wird neu injiziert. Bei MKV/AV1 übernimmt libsvtav1 die Profil-10-RPU direkt während des Encodes; dovi_tool kann RPU-Metadaten nicht nachträglich in AV1 injizieren. Skalierte dynamische HDR-Ausgaben werden derzeit bewusst abgelehnt, weil Level-5-Aktivflächen nicht sicher proportional angepasst werden können; das 1080p-HDR-Standardprofil verwirft deshalb dynamische Metadaten.

Vor dem Upload durchläuft jede fertige Datei ein verbindliches Validierungs-Gate. Es prüft Dekodierbarkeit an verteilten Stichproben, schwarze Ausgaben, Codec, Auflösung, Laufzeit, Audio-/Untertitelanzahl sowie HDR-Signalisierung. Nur bestandene Outputs gelangen in den weiterhin Lease-geschützten atomaren Publish-Schritt. Pipeline, Fallback-Grund und Prüfbericht bleiben im Job und im Output-State sichtbar. Gleichzeitige Jobs reservieren ihren geschätzten /work-Bedarf atomar; worker.work_reserve_bytes hält standardmäßig zusätzlich 1 GiB frei.

Wichtige Mounts

OPTIMIZARR_CONFIG_PATH=/mnt/user/appdata/optimizarr/config
OPTIMIZARR_MOVIES_PATH=/mnt/user/media/movies
OPTIMIZARR_TV_PATH=/mnt/user/media/tv
OPTIMIZARR_OUTPUT_PATH=/mnt/user/media/optimized
OPTIMIZARR_WORK_PATH=/mnt/cache/appdata/optimizarr/work
OPTIMIZARR_API_PORT=8097

Quellen bleiben :ro. /work sollte lokal und schnell sein. Das physische Output-Verzeichnis muss API und Worker gemeinsam zur Verfügung stehen; die Containerpfade dürfen durch die Worker-Zuordnung unterschiedlich heißen. Nur die API darf eine versteckte Upload-Datei final veröffentlichen.

Upgrade von 0.9

Beim API-Start wird der Redis-Namensraum einmalig von plex-optimizer:* nach optimizarr:* migriert. Sind beide Namensräume befüllt, bricht der Start absichtlich ab. Standardprofil-IDs und deren Referenzen werden migriert; selbst angelegte IDs bleiben unverändert. Bestehende Ableitungsdateien werden weder verschoben noch gelöscht. Vor dem Upgrade Redis, /config/runtime und Compose sichern und alte Worker stoppen.

Alte Variablennamen werden nur beim Upgrade gelesen. Neue Deployments sollten ausschließlich OPTIMIZARR_* verwenden.

Entwicklung

python -m pytest -q
python -m py_compile app/*.py
docker compose -f compose.yml config >/dev/null
docker compose -f compose.yml -f compose.qsv.yml config >/dev/null
docker compose -f compose.yml -f compose.vaapi.yml config >/dev/null
docker compose -f compose.yml -f compose.nvidia.yml config >/dev/null
docker build --target test --progress plain .
docker build -t optimizarr:test .

Dedizierte Hardware-Runner prüfen QSV, VAAPI und optional NVENC mit selbst erzeugten SDR-, gecroppten 4K/HDR10- und HDR→SDR-Dateien gegen die echte Optimizarr-Pipeline. Die Suite läuft manuell, nachts und für Release-Tags; NVENC testet zusätzlich die konfigurierte parallele Sitzungszahl. Voraussetzungen und lokale Ausführung stehen in docs/HARDWARE_TESTING.md.

Fehlerdetails erscheinen im Dashboard-Tooltip. Terminale Jobs können neu gestartet und Jobs in jedem Zustand entfernt werden. Bei aktiven Jobs widerruft das Entfernen zuerst die Lease; FFmpeg wird beendet und Worker-Staging sowie unvollständige Uploads werden bereinigt, ohne Quellmedien anzufassen.

Die Jobhistorie wird serverseitig paginiert, gefiltert und über Redis-Indizes global sortiert. Status, Profil, Worker, Medientyp und freie Suche können kombiniert werden. Terminale Jobdatensätze werden standardmäßig nach 90 Tagen entfernt; die Aufbewahrung ist unter Administration → Einstellungen → Job-Historie konfigurierbar und verändert weder Medienindex noch Outputs.

Unter Administration → System → Backup und Restore können portable, checksummierte Archive erzeugt, heruntergeladen, hochgeladen, geprüft und wiederhergestellt werden. Tägliche Backups laufen standardmäßig um 03:00 Uhr; die letzten sieben Archive bleiben erhalten. /config/backups ist in Compose explizit gemountet. Archive enthalten den Redis-Anwendungszustand, settings.key und gegebenenfalls den lokalen Worker-Token und sind deshalb vertraulich. Ein Restore ist nur mit leerer Queue möglich, erzeugt vorher ein Sicherheitsbackup, verwirft flüchtige Sessions und Leases und berührt keine Mediendateien.

Das Dashboard sammelt minutenweise Werte für 24 Stunden und stündliche Werte für 30 Tage. Es warnt vor offline gegangenen Workern, knappem Worker-Speicher (unter Berücksichtigung laufender Reservierungen), gehäuften Profilfehlern, zu alten Queue-Einträgen und Lease-Recoveries. Schwellenwerte sowie ein optionaler HMAC-signierter Webhook werden unter Administration → Einstellungen → Monitoring und Warnungen verwaltet. Warnungen lassen sich bestätigen und lösen sich automatisch auf, sobald die Ursache verschwunden ist.