Cast Sender
CastSenderPlugin is the Chromecast sender for nomercy-video-player.
Register it when you want a Cast button in your player UI.
It manages the full CAF session lifecycle, mirrors RemotePlayer events back to the local event bus so currentTime, play state, and volume stay accurate while casting, and resumes local playback automatically when the Cast session ends.
Plugin id
'cast-sender'
Import
import { CastSenderPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type {
CastSenderOptions,
CastSenderEvents,
} from '@nomercy-entertainment/nomercy-video-player/plugins';
Prerequisites
The Google Cast SDK script must be loaded before the plugin’s use() runs:
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
What it does
CastSenderPlugin is a thin video-specific override of the player core’s shared CastSenderPlugin.
The shared base handles the SDK probe, session lifecycle, RemotePlayer event mirroring, and the resume-on-disconnect path.
The video subclass adds:
'video/mp4'as the default content type for video itemsbuildMetadata()override that picksTvShowMediaMetadata(whenitem.showis set) orGenericMediaMetadata, readingtitle,show,season,episode, andposterfrom theVideoPlaylistItemshape- Poster URL resolution via
this.resolveUrl(item.poster, 'poster'), so auth tokens andbaseImageUrlare applied
Player events (play, pause, stop, seek) are forwarded to the active Cast session via RemotePlayerController only when the event payload does not carry source: 'cast'.
volume and mute events are forwarded without a source check - they are suppressed only while the bridge is applying a receiver update internally.
In environments without the Cast SDK (Firefox, JSDOM, every non-Chromium browser) the bridge stays passive.
connect() raises a BrowserPolicyError and all forwarders no-op gracefully.
Listeners are still attached so consumer UI can wire cast:* events before the SDK loads.
Options
| Option | Type | Default | Description |
|---|---|---|---|
chromecastAppId | string | undefined | Chromecast receiver app ID. Leave unset to use the built-in NoMercy receiver. |
enableAirPlay | boolean | undefined | Allow AirPlay sender on Safari. |
customReceiverNamespace | string | undefined | Custom CAF namespace for receiver messages. |
resumeLocalOnDisconnect | boolean | true | Resume local playback after Cast disconnects, restoring the receiver’s last position. |
defaultContentType | string | undefined | Override the MIME type used when the playlist item has no mime field. When omitted, the subclass defaultContentType() hook supplies the value ('video/mp4' for the video player). |
live | boolean | false | Treat the stream as a live (unbounded) source. |
Events
| Event | Payload | Description |
|---|---|---|
'cast:connected' | { deviceName: string } | Session established. |
'cast:disconnected' | void | Session ended. |
'cast:remote-state' | { time: number; state: 'playing' | 'paused' | 'buffering' } | Receiver playback state mirrored to local bus. |
'cast:media-changed' | { contentId: string } | Active media item changed on the receiver. |
'cast:error' | { error: Error } | Cast SDK or session error. |
'unsupported' | { reason: string } | Cast SDK not available in this environment. |
Consumer listeners use the plugin:<id>:<event> string form:
player.on('plugin:cast-sender:cast:connected', ({ deviceName }) => {
showCastingBanner(deviceName);
});
player.on('plugin:cast-sender:cast:disconnected', () => {
hideCastingBanner();
});
player.on('plugin:cast-sender:unsupported', ({ reason }) => {
hideCastButton();
});
Methods
import { CastSenderPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
const castPlugin = player.getPlugin(CastSenderPlugin)!;
// Open the Cast device picker and establish a session.
// Throws BrowserPolicyError when the Cast SDK is absent.
await castPlugin.connect();
// End the current session. Idempotent, safe to call when not connected.
// Emits cast:disconnected on success.
// Emits unsupported (and returns without casting) when the Cast SDK is absent.
castPlugin.disconnect();
// True while a Cast session is active.
const active = castPlugin.isConnected();
Registration
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { CastSenderPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
const player = nmplayer('player')
.addPlugin(CastSenderPlugin, { chromecastAppId: 'CC1AD845' })
.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',
},
],
});
Custom receiver
If you have a custom Cast receiver app, pass its application ID:
player.addPlugin(CastSenderPlugin, {
chromecastAppId: 'ABCD1234',
});
The receiver must support the same playlist item shape (url, title, subtitles, etc.) or a mapped equivalent.
Metadata building
The video CastSenderPlugin overrides buildMetadata() to pick the right metadata type:
- When
item.showis a non-empty string, it usesTvShowMediaMetadatawithseriesTitle,season, andepisodepopulated. - Otherwise it uses
GenericMediaMetadatawithtitleand an optionalsubtitlefromitem.show.
Poster artwork is resolved via this.resolveUrl(item.poster, 'poster'), so the player core’s auth pipeline applies.
nomercy-cast-player
The NoMercy cast receiver (nomercy-cast-player) is a Vue 3 app designed to pair with this plugin.
It is slated for a full rewrite to v2 in a future release.