# Jellyfin Trickplay Generator (Legacy Layout) Dieses Script erzeugt **Jellyfin-kompatible Trickplay-Tiles** im **Legacy-Layout** – also genauso, wie du es in deinem Medienordner beobachtet hast: ``` .trickplay/ 640 - 10x10/ 0.jpg 1.jpg ... ``` ✅ **Keine JSON-Datei** im Trickplay-Ordner (Legacy). ✅ **Parallelisierbar** (mehrere Medien gleichzeitig) – anders als Jellyfin intern. ✅ **Optional Hardware-Decode** via ffmpeg (`vaapi`, `qsv`, `cuda`, `d3d11va`, `amf`). ✅ **Resume/Incremental**: Generiert nur fehlende Auflösungen bzw. nur wenn Settings geändert wurden (per-Width Fingerprint). ✅ **Schöne Konsole** mit Fortschritt (optional via `rich`). --- ## Voraussetzungen ### Python - Windows: `py --version` - Linux: `python3 --version` ### ffmpeg + ffprobe Beide müssen verfügbar sein: ```bash ffmpeg -version ffprobe -version ``` Wenn nicht im PATH, kannst du die Pfade in `settings.ini` setzen. ### Python-Pakete Pflicht: ```bash pip install pillow ``` Optional (für hübsche Fortschrittsbalken): ```bash pip install rich ``` --- ## Installation (Windows Beispiel) ```powershell cd "C:\Users\Thorsten\Documents\Scripte" py -m pip install pillow rich py .\py_jellyfin_trickplay_generator.py ``` --- ## Installation (Linux Beispiel) ```bash cd /pfad/zum/script python3 -m pip install --user pillow rich python3 ./py_jellyfin_trickplay_generator.py ``` --- ## Konfiguration: `settings.ini` Beim ersten Start wird automatisch eine `settings.ini` im gleichen Ordner erstellt. Beispiel: ```ini [input] paths = L:\TV Serien\FSK 0 L:\Filme recursive = true [general] output = alongside out_dir = workers = 6 replace = false keep_temp = false loglevel = error jpeg_quality = 90 [trickplay] interval_ms = 10000 widths = 320,640 tile_cols = 10 tile_rows = 10 [ffmpeg] ffmpeg = ffprobe = hw = none hw_device = ``` ### Erklärung wichtiger Optionen #### `[input]` - `paths`: Eine oder mehrere Wurzeln. Multi-line empfohlen. - `recursive`: `true` findet Medien rekursiv in Unterordnern. #### `[general]` - `workers`: Anzahl paralleler Prozesse (Medien parallel). - `replace`: - `false`: Incremental/Resume (nur fehlende Widths / nur wenn Fingerprint nicht passt) - `true`: Alles neu (löscht vorhandene Trickplay-Daten für die Datei) - `output`: - `alongside` (Standard): direkt neben der Videodatei als `*.trickplay` - `dir`: in einem zentralen `out_dir` (selten sinnvoll für Jellyfin Legacy) - `loglevel`: ffmpeg Log-Level (`error`, `warning`, `info`, ...) #### `[trickplay]` - `interval_ms`: Abstand zwischen Thumbnails (10000ms = alle 10 Sekunden) - `widths`: Zielbreiten, z.B. `640` oder `320,640,720` - `tile_cols`, `tile_rows`: Grid der Tile-Spritesheets (z.B. `10x10`) #### `[ffmpeg]` - `hw` (Hardware-Decode): - `none` (Standard) - `vaapi` (Linux Intel/AMD iGPU, /dev/dri/…) - `qsv` (Intel QuickSync) - `cuda` (NVIDIA) - `d3d11va` (Windows: Intel/AMD/NVIDIA – Decode über D3D11) - `amf` (AMD – intern ebenfalls d3d11va für Decode genutzt) - `hw_device`: z.B. `/dev/dri/renderD128` bei VAAPI --- ## CLI Nutzung (Overrides) CLI-Argumente überschreiben Werte aus der INI: ```bash python3 py_jellyfin_trickplay_generator.py --workers 8 --widths 640 --interval-ms 10000 /pfad/zu/Medien ``` Rekursiv: ```bash python3 py_jellyfin_trickplay_generator.py --recursive /pfad/zu/Serien ``` --- ## Fortschritt / Konsole Wenn `rich` installiert ist, zeigt das Script: - **Overall** (Gesamtfortschritt Dateien) - **Worker** pro Prozess (Stage: probe / extract / tile / skip) Wenn `rich` fehlt, gibt es einfache Textausgaben pro Datei. --- ## Resume / Incremental Build (Marker-Dateien) Damit man erkennt, ob ein Durchlauf sauber fertig wurde und um nur fehlende Dinge zu generieren, werden Marker-Dateien genutzt. ### Root (pro Video) Im `*.trickplay` Root: - `.inprogress` → Job lief / wurde evtl. unterbrochen - `.complete` → Job komplett (für genau diese Job-Settings) - `.trickplay.job.json` → Job-Settings + Job-Fingerprint ### Pro Width In jedem Width-Ordner (z.B. `640 - 10x10/`): - `.inprogress` → diese Width wurde gerade gebaut - `.complete` → diese Width ist vollständig - `.meta.json` → Width-Settings + Width-Fingerprint **Wichtig:** Der Skip passiert nur, wenn - Tiles existieren (`0.jpg` vorhanden), - `.complete` existiert, - und `.meta.json`-Fingerprint zu den aktuellen Settings passt. So kannst du z.B. später `widths = 320,640,720` einstellen und es wird nur 720 nachgezogen. --- ## Typische Probleme ### `ffmpeg not found in PATH` - Windows: PowerShell neu öffnen nachdem ffmpeg installiert wurde - oder Pfade in `settings.ini` setzen: ```ini [ffmpeg] ffmpeg = C:\Tools\ffmpeg\bin\ffmpeg.exe ffprobe = C:\Tools\ffmpeg\bin\ffprobe.exe ``` ### `ModuleNotFoundError: No module named 'PIL'` ```bash pip install pillow ``` ### Windows: `python3` öffnet Microsoft Store Nutze: ```powershell py script.py ``` --- ## Notes - Das Script implementiert das beobachtete Jellyfin **Legacy** Trickplay-Layout. - Wenn Jellyfin in deiner Installation irgendwann auf ein anderes Layout umstellt (mit JSON/Manifest), müsste das Script entsprechend erweitert werden. --- --- ## ffmpeg Hardware-Decode (hw) – Details (Windows vs Linux) Wichtig: Das Script nutzt Hardware **nur fürs Decode** (Einlesen/Decodieren des Videos). Die Ausgabe ist weiterhin **MJPEG** (CPU), was für Trickplay/Thumbs völlig ok ist. ### Überblick: Welche `hw`-Option wo sinnvoll ist - **Windows** - `d3d11va` ✅ (empfohlen; Intel/AMD/NVIDIA – Decode über Direct3D 11) - `cuda` ✅ (NVIDIA Decode; meist stabil, braucht NVIDIA-Treiber + ffmpeg mit CUDA-Support) - `qsv` ✅ (Intel Quick Sync; benötigt Intel iGPU + Treiber; ffmpeg Build muss QSV unterstützen) - `amf` ⚠️ (AMD AMF ist in ffmpeg primär Windows-Stack; im Script wird fürs Decode intern ebenfalls `d3d11va` genutzt) - `vaapi` ❌ (VAAPI ist Linux/Unix-Stack) - **Linux** - `vaapi` ✅ (empfohlen für Intel iGPU & AMD GPUs über Mesa VAAPI) - `qsv` ✅ (Intel Quick Sync; je nach Distribution/ffmpeg Build) - `cuda` ✅ (NVIDIA; benötigt Treiber + ffmpeg mit CUDA/NVDEC) - `d3d11va` ❌ (Windows-only) - `amf` ❌/⚠️ (AMD AMF ist i.d.R. nicht der Linux-Standardpfad; auf Linux nimmst du für AMD fast immer `vaapi`) ### `hw_device` – wann braucht man das? Im Script wird `hw_device` derzeit **nur für `vaapi`** genutzt. #### VAAPI (Linux): Device angeben - Typisch: `hw = vaapi` - Device: **Render-Node** unter `/dev/dri/` Meist ist das: - `/dev/dri/renderD128` (sehr häufig) - oder `/dev/dri/renderD129` (wenn mehrere GPUs vorhanden) **So findest du die Render Nodes:** ```bash ls -l /dev/dri/ ``` Beispiel output: - `card0`, `card1` (Display devices) - `renderD128`, `renderD129` (Render nodes, die wir wollen) **Empfehlung:** immer den `renderD*` Node verwenden, nicht `card*`. In `settings.ini`: ```ini [ffmpeg] hw = vaapi hw_device = /dev/dri/renderD128 ``` #### QSV (Intel Quick Sync): Device meist leer lassen Im Script wird QSV aktuell so genutzt: - `-hwaccel qsv` In den meisten Fällen brauchst du **kein** `hw_device`. Wenn du später tiefer optimieren willst (z.B. spezielles QSV device), müsste man das Script erweitern. In `settings.ini`: ```ini [ffmpeg] hw = qsv hw_device = ``` #### CUDA (NVIDIA): Device leer lassen CUDA/NVDEC benötigt typischerweise kein Device-Argument (Treiber entscheidet). ```ini [ffmpeg] hw = cuda hw_device = ``` #### D3D11VA (Windows): Device leer lassen Direct3D 11 VA ist ein Windows-API; Device-Auswahl erfolgt automatisch. ```ini [ffmpeg] hw = d3d11va hw_device = ``` --- ## Troubleshooting Hardware-Decode ### 1) Erst testen, ob ffmpeg den hwaccel kennt ```bash ffmpeg -hide_banner -hwaccels ``` Da sollte z.B. `vaapi`, `qsv`, `cuda`, `d3d11va` auftauchen. ### 2) Linux VAAPI: Treiber/Stack - Intel: `intel-media-driver` (neuere Gen) oder `i965-va-driver` (älter) - AMD: Mesa VAAPI (`mesa-va-drivers`) Test: ```bash vainfo ``` Wenn `vainfo` schon Fehler wirft, wird ffmpeg mit `vaapi` auch zicken. ### 3) NVIDIA CUDA/NVDEC Wenn `ffmpeg -hwaccels` kein `cuda` zeigt, ist dein ffmpeg-Build evtl. ohne CUDA. ### 4) Wenn’s instabil ist Setze erst mal: ```ini [ffmpeg] hw = none ``` und prüfe, ob alles stabil durchläuft. Danach wieder mit `hw` testen. ### 5) Mehrere GPUs - Linux: VAAPI über `renderD128`/`renderD129` zielst du die GPU indirekt an. - Windows: D3D11VA/CUDA/QSV nutzen i.d.R. automatisch die passende Hardware; explizite Auswahl wäre möglich, ist aber derzeit im Script nicht vorgesehen.