- C# 72.3%
- HTML 19.8%
- Shell 7.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Die Datenbank ist crowd-sourced, mehrere Leute reichen also denselben Vorspann mit leicht abweichenden Zeitstempeln ein. Rick and Morty hat zum Beispiel 167 Intro-Einträge bei 91 Folgen. Die öffentliche API antwortet mit höchstens einem Eintrag je Typ — ihr Antwortobjekt hat je ein Feld intro/outro/recap/preview. Mein Provider gab dagegen alle aus, sodass Jellyfin zwei überlappende Intros bekam. Jetzt wird pro Typ der Eintrag mit der höchsten Confidence gewählt, bei Gleichstand der mit dem höheren Community-Score. Das ist dieselbe Auswahl, die auch die API trifft — nachgeprüft an Rick and Morty S01E01, wo sie den Eintrag mit passender Referenzlaufzeit dem ohne vorzieht. Wirkung auf die Bibliothek: 3495 -> 3167 Segmente, 328 Duplikate entfallen, betroffen waren 224 von 1521 Folgen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
| dist | ||
| Jellyfin.Plugin.SkipDb | ||
| .gitignore | ||
| build.sh | ||
| build.yaml | ||
| Directory.Build.props | ||
| LICENSE | ||
| manifest.json | ||
| package.sh | ||
| README.md | ||
jf-skipdbtv
Jellyfin-Plugin, das Intro-, Recap-, Outro- und Preview-Zeitstempel von skipdb.tv bezieht und über Jellyfins Media-Segment-API bereitstellt. Kompatible Clients zeigen daraufhin einen Skip-Button.
Kompatibilität
Ein Codestand, zwei Builds:
| Build | Jellyfin | Paket | Plugin-Version |
|---|---|---|---|
net9.0 |
10.11.x | Jellyfin.Controller 10.11.11 |
10.11.1.0 |
net10.0 |
12.0 | Jellyfin.Controller 12.0.0-rc5 |
12.0.1.0 |
Die Plugin-Version spiegelt die Ziel-Jellyfin-Version, wie es auch intro-skipper und SmartLists handhaben.
Der Unterschied zwischen beiden ist eine einzige Methode: IMediaSegmentProvider
hat ab Jellyfin 12 zusätzlich CleanupExtractedData. Sie wird über
#if NET10_0_OR_GREATER eingebunden. Alle Datentypen (MediaSegmentDto,
MediaSegmentGenerationRequest, MediaSegmentType) sind in beiden Versionen identisch.
Funktionsweise
Das Plugin fragt nicht pro Element bei der API nach. Ein Media-Segment-Scan ruft den Provider einmal je Bibliothekselement auf — bei einer mittleren Sammlung wären das mehrere tausend Anfragen gegen einen ehrenamtlich betriebenen Dienst, und das bei jedem Scan.
Stattdessen wird einmal täglich die komplette Datenbank geholt:
GET https://skipdb.tv/api/dump (~30 MB, 101.000 Segmente, täglich neu erzeugt)
Alle Abfragen laufen danach lokal gegen einen Index im Speicher. Der Sync schickt
den ETag des letzten Laufs mit; ist der Dump unverändert, antwortet der Server mit
304 und es wird nichts übertragen.
Aufwand im laufenden Betrieb: eine Anfrage pro Tag.
Zuordnung zur lokalen Datei
Rund 30 % der Einträge tragen keine Referenzlaufzeit, die übrigen schon. Weicht die Laufzeit deiner Datei davon ab, werden die Zeitstempel verschoben. Die Regeln habe ich gegen die öffentliche API ausgemessen und nachgebildet:
| Fall | Verhalten | Confidence |
|---|---|---|
| keine Referenzlaufzeit | unverändert übernehmen | 0,75 |
| Abweichung ≤ 2 s | gleicher Schnitt, unverändert | 0,90 |
| Abweichung ≤ 15 s, Datei kürzer | um die Differenz verschieben | 0,82 |
| Abweichung ≤ 15 s, Datei länger | unverändert (Mehrlänge sitzt meist vorn) | 0,82 |
| Abweichung > 15 s | anderer Schnitt, unverändert | 0,60 |
Über die Mindest-Confidence lassen sich damit unsichere Zuordnungen ausblenden.
Datenlizenz
Die Daten stehen unter ODbL 1.0 mit Service-Provider-Reciprocity. Wer sie nutzt, verpflichtet sich unter anderem, Verbesserungen zurückzugeben. Details unter skipdb.tv/license.
Einstellungen
Im Dashboard unter Plugins → SkipDB.tv:
- Segmenttypen einzeln ein-/ausschaltbar (Intro, Recap, Outro, Preview)
- Filme mitberücksichtigen (Standard: ja)
- Mindest-Confidence, Standard
0.5— SkipDB liefert pro Segment einen Wert zwischen 0 und 1, alles darunter wird verworfen - API-Basis-URL, nur für Spiegelserver relevant
Bauen
Ohne lokales .NET SDK, im Container:
./build.sh
Ergebnis:
Jellyfin.Plugin.SkipDb/bin/Release/net9.0/Jellyfin.Plugin.SkipDb.dll -> Jellyfin 10.11
Jellyfin.Plugin.SkipDb/bin/Release/net10.0/Jellyfin.Plugin.SkipDb.dll -> Jellyfin 12.0
Installation
1. Repository in Jellyfin eintragen
Dashboard → Plugins → Reiter Repositories → + (Repository hinzufügen). Zwei Felder ausfüllen:
| Feld | Wert |
|---|---|
| Name der Repository | jf-skipdbtv (frei wählbar) |
| Repository-URL | https://git.dkrtn.de/deko/jf-skipdbtv/raw/branch/main/manifest.json |
Speichern. Jellyfin lädt das Manifest sofort; bleibt die Liste leer, stimmt die
URL nicht oder der Server kommt nicht an git.dkrtn.de heran.
2. Plugin installieren
Reiter Katalog → Kategorie Metadata → SkipDB.tv → Installieren.
Das Manifest bietet zwei Versionen an. Jellyfin vergleicht deren targetAbi
mit der eigenen Version und wählt selbst:
| Dein Jellyfin | installierte Version |
|---|---|
| 10.11.x | 10.11.1.0 |
| 12.0 | 12.0.1.0 |
3. Jellyfin neu starten
Frisch installierte Plugins werden erst beim Start geladen. Vorher steht das
Plugin unter Meine Plugins auf Restart. Danach auf Active.
4. Segmente holen lassen
Das ist der Schritt, den man leicht übersieht: Jellyfin ruft Segment-Provider nicht beim Bibliotheks-Scan auf, sondern in einer eigenen Aufgabe. Ohne sie bleiben alle Episoden bei null Segmenten, obwohl das Plugin korrekt läuft.
Zwei Aufgaben unter Dashboard → Geplante Aufgaben:
- Sync SkipDB database — lädt die Datenbank. Läuft automatisch beim Serverstart und danach täglich um 7 Uhr; für den ersten Lauf kann man sie von Hand anstoßen.
- Media Segment Scan — verteilt die Segmente auf die Bibliothek.
Im Log erscheint dann pro Datei eine Zeile:
Media Segment provider SkipDB.tv found 3 for /media/Attack on Titan (2013)/...
Die Aufgabe läuft danach nach Zeitplan weiter und erfasst neu hinzugekommene Folgen automatisch.
Konfiguration
Dashboard → Plugins → Meine Plugins → SkipDB.tv. Dort lassen sich die Segmenttypen einzeln abschalten, Filme ein- oder ausschließen und die Mindest-Confidence setzen.
Ohne Repository, von Hand
Das passende Zip aus dist/ nach <jellyfin-data>/plugins/SkipDB.tv_<version>/
entpacken und neu starten. Bei einer apt-Installation ist das
/var/lib/jellyfin/plugins/, im offiziellen Docker-Image /config/plugins/.
Release bauen
./package.sh
Baut beide Ziele, packt je ein Zip nach dist/, berechnet die MD5-Summen und
schreibt manifest.json. Danach committen und pushen — die sourceUrl im
Manifest zeigt auf die Raw-URLs dieses Repositories, die Zips müssen also
eingecheckt sein.
Status
Erste Fassung. In einer Stichprobe über 26 Serien lag die Trefferquote der Datenbank bei rund 46 %, bei Anime deutlich höher als bei alten Zeichentrickserien. Ergänzt sich gut mit Intro Skipper, das lokal per Audio-Fingerprint erkennt und kein Internet braucht.