jellyfinplugin für die metadaten (intro, outro etc.) von skipdb.tv
  • C# 72.3%
  • HTML 19.8%
  • Shell 7.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
deko 56b0bed0c8 fix: pro Segmenttyp nur den besten Eintrag liefern
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>
2026-08-25 16:31:32 +02:00
dist fix: pro Segmenttyp nur den besten Eintrag liefern 2026-08-25 16:31:32 +02:00
Jellyfin.Plugin.SkipDb fix: pro Segmenttyp nur den besten Eintrag liefern 2026-08-25 16:31:32 +02:00
.gitignore feat: Auslieferung über Jellyfin-Plugin-Repository 2026-08-25 15:31:41 +02:00
build.sh feat: Media-Segment-Provider für SkipDB.tv 2026-08-25 15:26:25 +02:00
build.yaml feat: Media-Segment-Provider für SkipDB.tv 2026-08-25 15:26:25 +02:00
Directory.Build.props feat: Media-Segment-Provider für SkipDB.tv 2026-08-25 15:26:25 +02:00
LICENSE feat: Media-Segment-Provider für SkipDB.tv 2026-08-25 15:26:25 +02:00
manifest.json fix: pro Segmenttyp nur den besten Eintrag liefern 2026-08-25 16:31:32 +02:00
package.sh fix: pro Segmenttyp nur den besten Eintrag liefern 2026-08-25 16:31:32 +02:00
README.md feat: Datenbank als Tagesdump laden statt pro Element abfragen 2026-08-25 15:58:01 +02:00

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:

  1. 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.
  2. 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.