Files
py_jellyfin_trickplay_gener…/README.md
2026-02-12 09:34:07 +01:00

8.4 KiB
Raw Blame History

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:

<VideoDatei>.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:

ffmpeg -version
ffprobe -version

Wenn nicht im PATH, kannst du die Pfade in settings.ini setzen.

Python-Pakete

Pflicht:

pip install pillow

Optional (für hübsche Fortschrittsbalken):

pip install rich

Installation (Windows Beispiel)

cd "C:\Users\Thorsten\Documents\Scripte"
py -m pip install pillow rich
py .\py_jellyfin_trickplay_generator.py

Installation (Linux Beispiel)

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:

[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:

python3 py_jellyfin_trickplay_generator.py --workers 8 --widths 640 --interval-ms 10000 /pfad/zu/Medien

Rekursiv:

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:
[ffmpeg]
ffmpeg = C:\Tools\ffmpeg\bin\ffmpeg.exe
ffprobe = C:\Tools\ffmpeg\bin\ffprobe.exe

ModuleNotFoundError: No module named 'PIL'

pip install pillow

Windows: python3 öffnet Microsoft Store

Nutze:

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:

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:

[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:

[ffmpeg]
hw = qsv
hw_device =

CUDA (NVIDIA): Device leer lassen

CUDA/NVDEC benötigt typischerweise kein Device-Argument (Treiber entscheidet).

[ffmpeg]
hw = cuda
hw_device =

D3D11VA (Windows): Device leer lassen

Direct3D 11 VA ist ein Windows-API; Device-Auswahl erfolgt automatisch.

[ffmpeg]
hw = d3d11va
hw_device =

Troubleshooting Hardware-Decode

1) Erst testen, ob ffmpeg den hwaccel kennt

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:

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) Wenns instabil ist

Setze erst mal:

[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.