Skip to content

Plugin: TV Key Handler

TvKeyHandlerPlugin (id 'tv-key-handler') adapts KeyHandlerPlugin for TV remote input. It inherits the full desktop default set (color buttons, universal media keys, modifier seeks, chapters, speed, frame-advance, subtitle size, stop) and overrides only the groups that behave differently when the input device is a remote, not a keyboard with focusable page elements.

Options

OptionTypeDefaultPurpose
arrowSeekSecondsnumber5Seconds ArrowLeft/ArrowRight seek on TV. Color-button seeks (30/60/90/120s) are fixed and unaffected.
infoDisplayMsnumber5000How long the Info OSD stays visible before auto-dismissing.

Every option from the base KeyHandlerPlugin (scope, bindings, extend, when, cooldownMs, disableMediaControls) still applies.

What changes from the desktop set

GroupDesktop behaviorTV behavior
ArrowLeft / ArrowRightGated off when isTv() (assumed to control page focus instead).Seek directly, arrowSeekSeconds each. The host page is expected to remove focus from interactive elements before mounting this plugin.
ArrowUp / ArrowDownGated off on TV in the desktop plugin.Enabled, volumeUp() / volumeDown() fire directly so a web-based TV shell can forward them to the system mixer or handle them in-player.
a / BrowserFavoritesCycles aspect ratio silently.Cycles aspect ratio and shows an OSD confirmation, there is no visible control bar on a TV to reflect the change otherwise.
? (help)Bound as shift+?, calls DesktopUiPlugin.toggleShortcuts() directly via getPlugin().Bound as plain ? (not shift+?) and emits plugin:tv-key-handler:shortcuts-toggle instead, a TV shortcuts overlay registers independently from the desktop UI one.

New groups this plugin adds on top of the inherited set:

  • Info: shows an OSD with title, current chapter, time and remaining time. Also emits plugin:tv-key-handler:info with the same data so a TV shell can render its own overlay instead of (or alongside) the built-in OSD message.
  • MediaRecord: emits plugin:tv-key-handler:bookmark with the current playback time. The plugin does not persist bookmarks itself, that is the consumer’s job; a missing listener is a silent no-op.

Rules & restrictions

  • OSD messages route through MessagePlugin when it is mounted on the player, and always also emit 'display-message' for consumers that prefer the event surface over adding MessagePlugin.
  • All bindings call local player methods directly. A NoMercy Connect integration that wants remote commands routed through a socket instead calls keyHandler.replace(combo, fn) (inherited from the kit base) to swap individual bindings, this plugin has no built-in awareness of Connect.
  • Translations (the Info OSD strings, aspect-ratio label, chapter labels) are auto-discovered from the plugin’s own ./i18n/*.ts bundle. The static translations field overrides the base KeyHandlerPlugin’s rather than extending it, so registering this plugin merges only its own keys into the player’s shared translation table (namespaced under plugin.tv-key-handler.*, removed again on dispose).

How to extend it

Override one group the same way as the desktop plugin, or add a TV-only group entirely:

TypeScript
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { TvKeyHandlerPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';

const player = nmplayer('player');

class MyTvKeyHandler extends TvKeyHandlerPlugin {
protected addBackKey(): void {
this.bind('GoBack', () => { this.player.emit('back', undefined); });
}

protected override addDefaults(): void {
super.addDefaults();
this.addBackKey();
}
}

player.addPlugin(MyTvKeyHandler, { arrowSeekSeconds: 10 });

Next steps

  • Plugin: Desktop UI: the overlay the desktop key handler’s shift+? opens via toggleShortcuts().