TV Key Handler
TvKeyHandlerPlugin gives you the remote-control binding layer for TV environments.
Use it alongside (or instead of) DesktopUiPlugin on Android TV, smart TV, or any deployment where an IR remote or D-pad is the primary input.
It subclasses KeyHandlerPlugin to inherit the full default video keyboard binding set, then overrides only the groups that work differently on a TV and adds two TV-only keys.
Plugin id
'tv-key-handler'
Import
import { TvKeyHandlerPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type { TvKeyHandlerOptions } from '@nomercy-entertainment/nomercy-video-player/plugins';
What it does
TvKeyHandlerPlugin extends KeyHandlerPlugin and changes these bindings:
| Binding group | TV-specific behaviour |
|---|---|
| Arrow keys | Seek directly. On a TV the host page removes focus from interactive elements before mounting the player, so arrows are free to drive playback. |
| Volume arrows | Enabled. The base plugin disables them on TV; this plugin re-enables them so a web TV shell can forward volume events correctly. |
| Aspect ratio | a and BrowserFavorites cycle aspect ratio and show an OSD message confirming the change, since there is no visible control bar. |
| Info key | Shows an OSD with title, chapter, current time, and time remaining. Also emits 'plugin:tv-key-handler:info' for an external TV shell overlay. |
| MediaRecord | Emits 'plugin:tv-key-handler:bookmark' with the current time. The player does not store bookmarks itself. |
Help key (?) | Emits 'plugin:tv-key-handler:shortcuts-toggle' instead of 'plugin:desktop-ui:shortcuts-toggle' so a TV shortcuts overlay can be wired independently. |
All Color-button (F0 through F3), BrowserFavorites, universal media key, modifier-seek, chapter, speed, frame-advance, subtitle-size, and stop bindings are inherited from KeyHandlerPlugin unchanged.
Options
| Option | Type | Default | Description |
|---|---|---|---|
arrowSeekSeconds | number | 5 | Seconds to seek when ArrowLeft or ArrowRight is pressed. Color-button seeks are fixed at 30/60/90/120 s and are not affected by this option. |
infoDisplayMs | number | 5000 | Milliseconds the Info OSD stays visible before it auto-dismisses. |
Events
| Event | Payload | Description |
|---|---|---|
'plugin:tv-key-handler:info' | { title: string, currentTime: number, duration: number, remaining: number, chapterLabel: string } | Info key pressed. Fired before the built-in OSD message so a TV shell can render its own overlay. |
'plugin:tv-key-handler:bookmark' | { time: number } | MediaRecord key pressed. Consumer should persist the bookmark; the player does not. |
'plugin:tv-key-handler:shortcuts-toggle' | void | Help key pressed. For a TV shortcuts overlay registered independently from the desktop-ui overlay. |
Methods
TvKeyHandlerPlugin exposes no additional public methods beyond those inherited from KeyHandlerPlugin.
Registration
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { TvKeyHandlerPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type { TvKeyHandlerOptions } from '@nomercy-entertainment/nomercy-video-player/plugins';
const player = nmplayer('player')
.addPlugin(TvKeyHandlerPlugin, {
arrowSeekSeconds: 5,
infoDisplayMs: 4000,
} as TvKeyHandlerOptions)
.setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Films',
playlist: [
{
id: 1,
title: 'Tears of Steel',
url: '/Tears.of.Steel.(2012)/Tears.of.Steel.(2012).NoMercy.m3u8',
chapters: [{ index: 0, title: 'Opening', start: 0, end: 120 }],
},
],
});
player.on('plugin:tv-key-handler:bookmark', ({ time }) => {
saveBookmark(time);
});
Info OSD content
When the Info key is pressed the OSD message is built from three parts.
First, the item title from player.item()?.title.
Second, the chapter label: chapter number plus title from the active chapter at the current time, or chapter number alone if the chapter has no title.
Third, currentTime / -remaining formatted as M:SS or H:MM:SS (minutes are not zero-padded; 65 seconds renders as 1:05).
The parts are joined with a · separator and sent as a single OSD message.
The full payload is also emitted as 'plugin:tv-key-handler:info' so an external shell can render its own overlay.
When a MessagePlugin is mounted the OSD routes through it; the plugin also emits display-message for consumers that prefer the event surface.
NoMercy Connect routing
All bindings call local player methods directly.
A consumer-side NoMercy Connect plugin can call keyHandler.replace(combo, fn) to route specific commands through a sync socket instead.