Custom Plugin (Music)
Music plugins extend the player core Plugin<NMMusicPlayer<any>, YourOptions, YourEvents> base class.
This gives you typed access to this.player as an NMMusicPlayer with all music-specific methods (backend(), crossfadeTo(), isTransitioning()).
For the general plugin authoring guide (lifecycle, this.on, this.emit, this.fetch, this.logger), see Writing Plugins in the player core docs.
Minimal music plugin
TypeScript
import { Plugin } from '@nomercy-entertainment/nomercy-player-core';
import type { NMMusicPlayer } from '@nomercy-entertainment/nomercy-music-player';
interface MyMusicOptions {
logEveryLine: boolean;
}
export class MyMusicPlugin extends Plugin<NMMusicPlayer<any>, MyMusicOptions> {
static override readonly id = 'my-music-plugin';
static override readonly version = '1.0.0';
override use(): void {
// this.player is typed as NMMusicPlayer<any> here
this.on('current', ({ item }) => {
if (item) {
console.log('Now playing:', item.name);
// Access music-specific fields:
console.log('Artist:', item.artist);
}
});
this.on('trackEndingSoon', ({ remaining, currentTrack }) => {
if (this.opts?.logEveryLine) {
console.log(`Track "${currentTrack.name}" ends in ${remaining.toFixed(1)}s`);
}
});
}
}
Accessing the audio backend
TypeScript
override use(): void {
this.on('ready', () => {
const backend = this.player.backend();
console.log('Backend kind:', backend.kind);
// Connect an analyser to the output:
const ctx = this.player.audioContext();
if (ctx) {
const analyser = ctx.createAnalyser();
backend.outputNode(ctx).connect(analyser);
analyser.connect(ctx.destination);
this.startVisualization(analyser);
}
});
}
Initiating a crossfade from a plugin
TypeScript
override use(): void {
this.on('ended', () => {
const next = this.player.peekNext();
if (!next || this.player.isTransitioning()) return;
void this.player.crossfadeTo(next, {
duration: 3,
})
.catch(err => this.logger.warn('crossfadeTo failed', err));
});
}
Emitting custom events
TypeScript
interface BeatEvents {
'beat:detected': { bpm: number; confidence: number };
}
export class BeatDetectorPlugin extends Plugin<NMMusicPlayer<any>, {}, BeatEvents> {
static override readonly id = 'beat-detector';
override use(): void {
this.on('play', () => {
void this.detectBeat();
});
}
private async detectBeat(): Promise<void> {
// … analysis …
this.emit('beat:detected', {
bpm: 128,
confidence: 0.92,
});
}
}
// Usage:
player.on('plugin:beat-detector:beat:detected', ({ bpm, confidence }) => {
console.log(`BPM: ${bpm} (${(confidence * 100).toFixed(0)}% confidence)`);
});
Registration
TypeScript
import { MyMusicPlugin } from './my-music-plugin';
const player = nmMPlayer('main')
.addPlugin(MyMusicPlugin, { logEveryLine: true })
.setup({ playlist: myTracks });
See also
- Player Core, Writing Plugins for the full plugin authoring guide (lifecycle, helpers, i18n)
- IAudioBackend for methods available via
this.player.backend() - Events for
MusicEventMapevents available viathis.on(...)