8.4 KiB
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:truefindet 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*.trickplaydir: in einem zentralenout_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.640oder320,640,720tile_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/renderD128bei 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.jpgvorhanden), .completeexistiert,- 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.inisetzen:
[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 ebenfallsd3d11vagenutzt)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 immervaapi)
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) oderi965-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) Wenn’s 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/renderD129zielst 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.