A Jellyfin server plugin that fetches skip-segment timestamps (intro, recap, credits, preview,
and commercial) from a self-hosted Open Media Essentials
API instance and exposes them as Jellyfin media segments via the
IMediaSegmentProvider interface.
Skip buttons appear natively in the Jellyfin web client during playback — no Custom JavaScript injection required.
Requirements: Jellyfin 10.9+. Items need TMDB metadata for the plugin to find segments.
- The plugin registers an
IMediaSegmentProviderwith Jellyfin. - When the Media Segment Scan scheduled task runs (manually or on schedule), Jellyfin calls the provider for each item in your library.
- The provider extracts the TMDB id, season, episode, and
RunTimeTicksfrom the item, then callsGET /manifeston your OME instance:GET /manifest?tmdb=<id>&season=<n>&episode=<n>&duration_ms=<ms> - The manifest response is mapped to
MediaSegmentDtoentries and returned to Jellyfin. The web client renders skip buttons for each segment at the appropriate time. - A 404 from OME (no ingest within the 60-second duration tolerance) is treated as "no segments" — not an error.
No API key is required. OME reads are open.
cd apps/jellyfin-plugin
dotnet build -c ReleaseCopy OpenMediaEssentials/bin/Release/net9.0/OpenMediaEssentials.dll into your Jellyfin plugins
folder:
- Linux/macOS:
~/.local/share/jellyfin/plugins/OpenMediaEssentials/ - Windows:
%LocalAppData%\jellyfin\plugins\OpenMediaEssentials\
Restart Jellyfin.
Not yet submitted to the Jellyfin plugin catalog. Once published:
- Dashboard → Plugins → Repositories → Add
- Add the manifest URL (TBD)
- Install from Catalog
Dashboard → Plugins → Open Media Essentials
| Setting | Default | Description |
|---|---|---|
| OME API URL | http://localhost:3006 |
Base URL of your OME instance. No trailing slash. |
| Request timeout | 3000 ms | HTTP timeout for manifest fetches. |
| Enable intro | on | Include intro segments. |
| Enable recap | on | Include recap (previously-on) segments. |
| Enable credits | on | Include credits / outro segments. |
| Enable preview | on | Include next-episode preview segments. |
| Enable commercial | off | Include commercial break segments. |
After changing settings, run Dashboard → Scheduled Tasks → Media Segment Scan to repopulate.
OME type |
Jellyfin MediaSegmentType |
|---|---|
intro |
Intro |
recap |
Recap |
credits |
Outro |
preview |
Preview |
commercial |
Commercial |
- Does not write data to OME. Ingest is a CLI concern (
ome --file), not a player concern. - Does not inject subtitle URLs. The manifest includes subtitle tracks, but Jellyfin manages subtitles through its own stream pipeline. Subtitle injection is a future concern.
- Does not detect segments. OME owns detection via ffprobe chapters. The plugin only reads.
apps/jellyfin-plugin/
├── OpenMediaEssentials/
│ ├── Plugin.cs # Main plugin class
│ ├── PluginServiceRegistrator.cs # DI registration
│ ├── Configuration/
│ │ ├── PluginConfiguration.cs # Config model
│ │ └── configPage.html # Dashboard config UI
│ ├── Api/
│ │ ├── ManifestResponse.cs # OME manifest response models
│ │ └── OmeClient.cs # HTTP client for GET /manifest
│ └── Providers/
│ └── OmeSegmentProvider.cs # IMediaSegmentProvider impl
├── build.yaml # Jellyfin build metadata
├── manifest.json # Plugin catalog manifest
└── OpenMediaEssentials.sln # Solution file
Build and test:
dotnet build -c ReleaseThere are no unit tests yet. To manually test, point the plugin at a running OME instance with ingested episodes and run the Media Segment Scan task in Jellyfin.