Skipper
SkipperPlugin watches the playback position and fires events when the player enters a segment you have tagged as skippable.
You wire a “Skip Intro” button to those events, and when the viewer clicks it, plugin.skip() jumps the player past the end of the range.
For segments like recaps that nobody wants, set autoSkip and the plugin seeks without any UI at all.
Plugin id
'skipper'
Import
import { SkipperPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type {
SkipperOptions,
SkipperEvents,
SkipperKind,
SkipperRange,
} from '@nomercy-entertainment/nomercy-video-player/plugins';
import type { SkipperEntry } from '@nomercy-entertainment/nomercy-video-player/plugins/skipper';
What it does
The plugin reads currentItem.skippers?: { intro?, recap?, credits? } from the active playlist item.
On every time event it checks whether the current position falls inside one of those ranges.
If it does, and the kind is not in autoSkip, it emits 'skipper:available' so your UI can render a skip button.
If the kind is in autoSkip, it seeks to the range end immediately and emits 'skipper:skipped' with auto: true.
When the player leaves a range (by seeking, reaching the end, or the segment being skipped) the plugin emits 'skipper:hidden'.
SkipperKind is one of:
type SkipperKind = 'intro' | 'recap' | 'credits';
Options
| Option | Type | Default | Description |
|---|---|---|---|
autoSkip | ReadonlyArray<SkipperKind> | [] | Segment kinds to skip automatically, no UI shown. |
revealAfterMs | number | 0 | Delay in milliseconds before skipper:available is emitted after entering a range. |
Events
| Event | Payload | Description |
|---|---|---|
'skipper:available' | { kind: SkipperKind; range: SkipperRange } | Player entered a skippable range. Render your skip button. |
'skipper:hidden' | { kind: SkipperKind } | Player left the range or it was skipped. Hide the skip button. |
'skipper:skipped' | { kind: SkipperKind; range: SkipperRange; auto: boolean } | A range was jumped. auto: true when triggered by autoSkip. |
Subscribe from outside the plugin using the 'plugin:<id>:<event>' string form:
player.on('plugin:skipper:skipper:available', ({ kind, range }) => {
console.log('entered', kind, range);
});
Methods
skippers
plugin.skippers(): SkipperEntry[]
Returns the current playlist item’s skippable segments as a flat array of { kind, range } entries.
Returns [] when the current item has no skippers data.
skip
plugin.skip(kind?: SkipperKind): void
Jumps the player past the end of the named kind’s range.
If no kind is given, uses the currently active range.
Does nothing when no range is active and no kind is provided.
Always emits 'skipper:skipped' with auto: false.
fetchSkipFile
plugin.fetchSkipFile(url: string): Promise<SkipperEntry[]>
Fetches and parses a JSON skip file from url using the player core’s authenticated fetch client.
The file must be an array of { type: SkipperKind; start: number; end: number } objects.
Entries with unrecognised type values or non-numeric timestamps are silently dropped.
Useful when skip data is stored server-side separately from the playlist item.
Registration
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { SkipperPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
const player = nmplayer('player')
.addPlugin(SkipperPlugin, { autoSkip: ['recap'] })
.setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Films',
playlist: [
{
title: 'Tears of Steel',
url: '/Tears.of.Steel.(2012)/Tears.of.Steel.(2012).NoMercy.m3u8',
skippers: {
intro: { start: 5, end: 90 },
recap: { start: 0, end: 45 },
credits: { start: 700, end: 730 },
},
},
],
});
const skipperPlugin = player.getPlugin(SkipperPlugin);
const skipButton = document.querySelector<HTMLButtonElement>('#skip-btn')!;
player.on('plugin:skipper:skipper:available', ({ kind }) => {
skipButton.textContent = kind === 'intro' ? 'Skip Intro' : 'Skip Credits';
skipButton.style.display = 'block';
});
player.on('plugin:skipper:skipper:hidden', () => {
skipButton.style.display = 'none';
});
skipButton.addEventListener('click', () => {
skipperPlugin?.skip();
});
Loading skip data from your server
If skip segments are not bundled with the playlist item, call fetchSkipFile after setup:
player.on('current', async () => {
const segments = await skipperPlugin?.fetchSkipFile('https://api.example.com/skips/episode-42.json');
console.log('loaded segments', segments);
});