Subtitles & Text Tracks
Subtitle selection and subtitle rendering are two separate concerns. Most of what’s on this page, listing tracks, picking one, styling the text, is kit surface (nomercy-player-core’s mediaTracksMethods) that reads/writes state; cycleSubtitles() and subtitleState() are the two video-only additions on top, called out below where they appear. Painting the cue text on screen is a plugin’s job: SubtitleOverlayPlugin for VTT, OctopusPlugin for embedded-font ASS/SSA. Build a Player: Selectors hand-builds the picker UI that calls subtitle(idx), pair it with SubtitleOverlayPlugin to actually render the cue text. Neither is loaded by default, so selecting a track with no renderer registered changes state correctly but paints nothing.
Listing and selecting tracks
subtitles() returns the track list for the active item; subtitle() reads the current selection as { index, track } or null when off. subtitle(idx) selects by index, subtitle(null) turns subtitles off:
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
const player = nmplayer('player');
const tracks = player.subtitles(); // SubtitleTrack[]: { id, language?, label }
const current = player.subtitle(); // { index, track } | null
await player.subtitle(0); // select the first track
await player.subtitle(null); // off
cycleSubtitles() (defined on the video player, not the kit) walks off → 0 → 1 → ... → N-1 → off in one call, the binding a keyboard shortcut or remote’s “CC” button uses instead of resolving the next index by hand. subtitleState() (also video-only) returns SubtitleState.ON/OFF for a UI that only needs to know whether any track is active, without caring which one.
Auto-selecting a language
defaultSubtitleLanguage on VideoPlayerConfig auto-selects a track once the manifest resolves, matching an exact BCP-47 tag first, then a prefix ('en' matches a track tagged 'en-US'):
player.setup({
baseUrl,
playlist: [sintelItem],
defaultSubtitleLanguage: 'en',
});
No match leaves subtitles off, silently, no error and no fallback track forced on.
Styling
subtitleStyle() reads the current SubtitleStyle; subtitleStyle(patch) merges a partial patch onto it and emits subtitleStyle with the merged result, the event SubtitleOverlayPlugin listens for to repaint every active cue immediately:
player.subtitleStyle({ fontSize: 120, edgeStyle: 'dropShadow' });
The kit only owns the in-memory value and the event, persisting a user’s choice across sessions is your app’s job (or a preference plugin’s).
Next steps
- Audio Tracks: audioTracks(), audioTrack(), and the same selection shape applied to embedded audio renditions.