Skip to content

Playback State & Events

A UI reads state two ways: pull a typed reader when you need a value right now, or subscribe once and let the player push updates. Both come from the kit, video only adds the events specific to its own medium on top.

Typed state readers

These come straight from nomercy-player-core (see Core: Time & State for the full contract) and work identically here:

  • playState(): PlayState.IDLE / LOADING / PLAYING / PAUSED / STOPPED / ERROR.
  • bufferState(): BufferState.IDLE / LOADING / SEEKING / STALLED.
  • networkState(): NetworkState.ONLINE / OFFLINE / SLOW.
  • volumeState(): VolumeState.UNMUTED / MUTED (see Volume).
  • timeData(): one TimeState snapshot bundling position, duration, buffered, remaining, and percentage, computed together so the values agree at the moment of the call.
TypeScript
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { PlayState } from '@nomercy-entertainment/nomercy-video-player';

const player = nmplayer('player');

if (player.playState() === PlayState.PLAYING) {
// ...
}

const { position, duration, percentage } = player.timeData();

Video-specific events

Most of what’s below is unique to VideoEventMap, layered on top of the kit’s BaseEventMap (transport, queue, volume, i18n, the events every tour page so far has already covered). Three rows are the exception: firstFrame, level-switched, and subtitleCue are BaseEventMap members themselves, listed here because they matter most in a video context, nomercy-music-player and a raw nomercy-player-core consumer see the same three.

EventPayloadFires when
firstFramevoidThe first decoded frame paints.
waiting / canplay / stalledvoidBackend buffering signals, for a spinner.
levels{ levels }HLS manifest parsed; quality list is now populated.
level-switched{ level }ABR (or a manual quality() call) actually switched renditions.
audioTracks{ tracks }Audio-track list is now populated.
subtitleCueSubtitleCueChangeEvery cue change, sidecar VTT or native text track alike.
fullscreen / pip / theater{ active }The matching toggle settled.
aspectRatio{ value }aspectRatio() or cycleAspectRatio() changed the object-fit mode.
videoRect{ rect }The displayed content rectangle changed (resize, fullscreen, metadata).
segmentBoundary{ startSec, endSec, onEnd }A playSegment() window’s endSec was reached (see Chapters).
display-message / remove-message{ text, ms? } / voidOSD toast request/dismiss — the active UI plugin renders it.
back / closevoidNavigation intent from a UI plugin’s back/close button.
TypeScript
player.on('levels', ({ levels }) => {
// populate a quality menu now that the manifest is parsed
});

player.on('fullscreen', ({ active }) => {
// sync a fullscreen button's icon
});

videoRect() and its event exist so an overlay plugin (subtitles, a letterbox border, a click-to-seek layer) can align to the actual painted video area under object-fit: contain, not the container, which includes the letterbox padding.

Next steps