Skip segments
This page covers the buttons that let viewers skip intros, recaps, credits, previews and the commercials of recordings: where Polyfin gets them, how it finds the intros and the credits of local episodes in their audio and the commercial breaks of Live TV recordings, and how to set up the databases they come from.
How skip buttons work
Skip intro and credits buttons, under Settings › Content, is on by default. It gives apps the intros, recaps and credits to skip.
| Setting | Where | Default | What it does |
|---|---|---|---|
| Skip intro and credits buttons | Settings › Content | On | Gives apps the segments to skip. Off, apps get none, no segment database is asked, no episode's audio is read, and the commercials found in recordings are not given. |
Compared with Jellyfin:
- Turned off, the server behaves as a Jellyfin server without a segment provider.
For app developers:
- Turned off,
/MediaSegments/{id}lists none. - Turned on, the media sources of movies and episodes say
HasSegments: truewhile a database is asked, when the version's own chapters name an intro, a recap, a preview or credits (see Segments of each version), or when an intro or credits were found in the audio of an episode's local file (see Intros and credits found in local episodes' audio). The media source of a recording says it when commercial breaks were found in it (see Commercials of recordings). jellyfin-web asks for segments only then, by the identifier of the version it plays, which/MediaSegments/{id}takes as well as the title's. The title's identifier stands for its first version. /MediaSegments/{id}answers Jellyfin'sMediaSegmentDtolist, in ticks, filtered byincludeSegmentTypes, repeated or comma-separated. Apps choose what to do with each type; the server has no setting per type.
The three databases
The skip buttons come from three community databases: TheIntroDB, IntroDB and PublicMetaDB. Polyfin asks them about a title the first time an app asks for its segments.
For each kind of segment (intro, recap, credits, preview), the first database that has one gives it. The others fill the gaps.
- PublicMetaDB also brings recap and preview markers, on episodes, along with intros and credits.
- PublicMetaDB is asked only with an API key; see PublicMetaDB key.
- TheIntroDB answers without a key; see TheIntroDB key.
Segments of each version
The databases time a title once, but the versions addons offer may be cut differently. Once Polyfin has analyzed a version, on its first play, it fits the segments to that version:
- A file's own chapters win, for that file. When a version's chapters name an intro, a recap, a preview or credits, they give that version's segments of that type in place of the databases'. Other versions keep the databases'.
- Segments never pass the end. A segment ends at the latest where the version ends. One starting at or after its end is left out.
- Credits that run to the end stop 1 second early, so that the web player (jellyfin-web) offers its skip button. Skipping then lands a second before the end, and the next episode starts, or the movie ends.
- When the title's listed runtime is shorter than the file, such credits end exactly at the file's end instead. The web player then shows its "Up Next" card rather than a skip button.
- The web player shows neither while its controls are on screen when the credits start: it offers a segment only once, as playback enters it.
A version not analyzed yet gets the databases' segments as they are. Asking for its segments never starts an analysis.
Chapter names: Polyfin follows the default names of Jellyfin's Chapter Segments Provider plugin, adds French, and leaves out its commercial breaks. Names count in any letter case, with or without accents, as whole words.
- An intro: intro, introduction, opening, OP, "générique de début", "générique d'ouverture" or "ouverture". "Opening Credits" is an intro.
- A preview: preview, "next time on", "next on", "next episode", "sneak peek", "aperçu", "prochainement", "prochain épisode" or "à suivre".
- A recap: recap, previously, "last time on", "last on", "récapitulatif", "résumé", "précédemment" or "épisode précédent".
- Credits: credits (end or closing credits), closing, ending, ED, outro, "crédits", "générique de fin" or "générique final".
A name is tried as an intro, then as a preview, a recap and credits, as the plugin does: "Credits and Preview" is a preview. OP and ED count only as the whole name, maybe followed by a number: "OP", "op 1", "ED2" and "ED - 2" count, while "Ed Wood" and "OP Center" do not. Chapters with other names, such as "Chapter 2", give no segment. Chapters give segments even with no database asked.
A chapter's segment runs from its start to the next chapter's start, or to the version's end for the last chapter. Chapters of the same type in a row make one segment.
Why credits stop early: jellyfin-web shows no skip button for credits that reach the runtime the title is listed with, when something follows in its queue. Its video page shows its "Up Next" card instead, but only for credits that reach the end of the version it plays. Credits count as running to the end when they end within 2 seconds of it. They stop early only when the listed runtime is at least the version's length, and when they still last 3 seconds, as jellyfin-web ignores shorter segments.
Intros and credits found in local episodes' audio
An episode in a local folder whose file names no intro or credits in its chapters, of a series or a season the databases do not know, would have none to skip. Polyfin finds them in the audio instead: an intro is the stretch of audio the episodes of a season share near their start, credits the stretch they share near their end.
| Setting | Where | Default | What it does |
|---|---|---|---|
| Find intros and credits in local episodes' audio | Settings › Content | On | Compares the audio of the episodes of a local season to find their intro and their credits. Off, or with the skip buttons off, no audio is read and the segments found are not given. |
When: an episode of a local folder played with no intro or no credits from its chapters or a database has its season compared in the background.
- The season's other episodes have their intro and credits at their next play. The episode just played has them from its next play.
- Only seasons someone watches are read: nothing is read ahead of a play.
- Seasons are compared one at a time. FFmpeg reads the audio at the lowest priority, so that playback goes first.
- An episode added to a season already compared is compared with the others the next time one of them is played.
How: Polyfin reads the start of each episode of the season, its first quarter and 10 minutes at most, and its end, its last quarter and 10 minutes at most. FFmpeg decodes the audio, and Polyfin makes its fingerprint itself, so that any build of FFmpeg serves: FFmpeg's chromaprint muxer is an optional part of its builds, missing from some. Polyfin then compares the episodes in pairs: the longest stretch two episodes share at their start, from 15 seconds to 2 minutes, is each one's intro, and the longest they share at their end, from 15 seconds to 3 minutes, each one's credits.
- Credits end where the stretch shared ends: a scene after the credits, which differs from one episode to the next, is not skipped.
- Credits that run to the end follow the rules of Segments of each version: they stop 1 second early for the web player's skip button, or end at the file's end for its "Up Next" card when the listed runtime is shorter.
- Two files of the same episode, such as two versions, are not compared with each other: they share all their audio.
- Fingerprints and the segments found are kept in the database by file, with its path, size and modification time. A file is read once, and again only when it changes. A file that changed has no intro or credits until its season is compared again. Once a scan of a local folder finds a file gone or changed, what was kept of it is deleted.
Order: the audio only fills the gaps. A version's own chapters win, then the databases, then the audio, for intros and credits alike: an episode whose chapters name credits but no intro gets its credits from its chapters and its intro from the audio.
Limits:
- A season needs two episodes sharing the intro, or the credits. An episode alone in its season, or the only one with this intro or these credits, gets none.
- An intro or credits whose music changes within a season may be missed, or found only between the episodes that share the same music.
- Only episodes of local folders read as one file are compared, on the server's disk or on a share. Discs and disc images, which FFmpeg reads through their input, are not, nor are addons' files, whose start and end would have to be downloaded for every episode.
- An intro that starts after the first quarter of an episode, or after its first 10 minutes, is not found. Credits are found only within an episode's last quarter and its last 10 minutes: credits that start earlier are found from there on, and credits that end earlier are not found.
Commercials of recordings
A Live TV recording is the channel's stream as it aired, commercials included (see Live TV). Polyfin can find its commercial breaks, which apps then offer to skip as Commercial segments.
| Setting | Where | Default | What it does |
|---|---|---|---|
| Find commercials in recordings | Settings › Recordings | Off | Reads each recording once it ends to find its commercial breaks. Off, no recording is read. |
When: a recording is read once it is finished, partial recordings included, in the background.
- Recordings are read one at a time. FFmpeg reads them at the lowest priority, so that playback and recording go first.
- Find commercials in recordings, a task under System › Schedule, reads the recordings not read yet: those that ended while the setting was off or the server stopped, and those made before it was turned on. It runs every day, and when started by hand. While the setting is off, it reads nothing.
- A recording is read once. One where nothing was found is not read again.
How: FFmpeg decodes the recording's video, scaled down to a small picture as soon as it is decoded, and its audio, and marks the moments that are both black (its blackdetect filter) and silent (its silencedetect filter, below -50 dB). Channels part a programme from its commercials, and the commercials from one another, with such moments.
- A break is a run of pieces between such moments, each 5 to 90 seconds long, lasting 30 seconds to 8 minutes in all. A longer run is not a break.
- The recording's start counts as such a moment: a recording that starts early, as with Start recordings early, may open on a break.
- Two moments less than a second apart count as one, as a fade to black flickers.
- A break runs from the start of the moment before it to the end of the moment after it, so that skipping it lands on the programme.
- A black scene in silence within a programme is one moment alone: it parts no commercials, and gives none.
Served: while Skip intro and credits buttons is on, /MediaSegments/{id} lists the breaks of a recording as Commercial segments, and its media source says HasSegments: true. Apps act on them as each user chose in their app's playback settings: jellyfin-web, for instance, skips commercials, asks first, or plays them, by its setting for that segment type. Users get the segments of the recordings they see, as for the recordings themselves.
Kept: what was found is kept with the recording, by its identifier: it stays when the recording's file is replaced, and is deleted with the recording.
Limits:
- A recording longer than 4 hours is not read, and gets none.
- A reading that takes longer than the recording lasts stops, and the recording gets none, as on a server too slow to decode its video.
- A recording without video or without sound gets none.
- On channels that do not part their commercials with moments both black and silent, breaks are missed.
Source order
By default the databases are preferred in the order TheIntroDB, IntroDB, PublicMetaDB, all on. At the first start, POLYFIN_SEGMENTS gives the order and which are on; see Configuration.
Skip marker sources, under Settings › Content below the skip buttons, lists the three databases with arrows to move them and a switch to turn each on or off. PublicMetaDB, on without a key, is marked as needing one.
The order and the switches apply at once when saved, to the answers already kept too. A database turned off is never asked, wherever it is in the list.
PublicMetaDB key
PublicMetaDB is asked only with an API key. Create one on PublicMetaDB under Settings → API, then paste it in PublicMetaDB key under Settings › Content.
| Setting | Where | Default | What it does |
|---|---|---|---|
| PublicMetaDB key | Settings › Content | Empty | API key PublicMetaDB is asked with. Without one, PublicMetaDB is not asked. |
- Polyfin checks the key with PublicMetaDB before saving it. It refuses a key PublicMetaDB refuses, or cannot be asked about.
- The key is never logged, and never sent back with the settings. It shows as dots; administrators can show it again with its eye (see Showing a saved key). With
POLYFIN_SECRET_KEYset, it is stored encrypted (see Stored keys and tokens). - An empty field removes the key.
- Saving, changing or removing the key applies at once, without a restart.
- Titles asked about before a key was saved are asked again once one is.
- Should PublicMetaDB refuse the key later, Polyfin logs it once and asks no more until another key is saved.
How PublicMetaDB matches titles
PublicMetaDB knows titles by their TMDB identifier only: a movie's, or a series' with the season and episode numbers. It keeps one record per contributor and release. Polyfin uses the record of a streaming release giving the most segments, the latest first.
TheIntroDB key
TheIntroDB key (optional), next to the PublicMetaDB key, is a TheIntroDB API key.
| Setting | Where | Default | What it does |
|---|---|---|---|
| TheIntroDB key (optional) | Settings › Content | Empty | Raises TheIntroDB's daily limit and includes your own submissions. |
TheIntroDB answers without a key. With one:
- its daily limit goes from 500 requests per address to 1,000 per account;
- its answers include your own submissions, even pending ones, weighted more.
How the key is checked
TheIntroDB's answers ignore a key they do not know. So Polyfin checks the key before saving it, by sending TheIntroDB an empty submission with it, which submits nothing.
- The key is saved when TheIntroDB only refuses the empty submission.
- It is refused when TheIntroDB refuses the key.
- It is not saved either when TheIntroDB cannot be asked, or answers otherwise.
The key is kept secret, shown and stored like PublicMetaDB's, and applied at once. Should TheIntroDB refuse it later, Polyfin logs it once and keeps asking TheIntroDB without it until another key is saved.
Caching
Polyfin keeps the databases' answers:
- 30 days when they found segments;
- a day when they found none;
- an hour after a failure.
A database that answers 429 with a Retry-After is asked about no title until then.