Skip to content

Quick Start

A working music player in a few lines: it loads your first track, starts playback, and surfaces system media controls (lock screen, notification) with the track metadata.

Install

Code
npm install @nomercy-entertainment/nomercy-music-player@beta

Requires Node 18+ for tooling. Runs in any modern browser.

Minimal working player

TypeScript
import nmMPlayer from '@nomercy-entertainment/nomercy-music-player';
import {
AutoAdvancePlugin,
MediaSessionPlugin,
} from '@nomercy-entertainment/nomercy-music-player/plugins';
import type {
MusicPlayerConfig,
MusicPlaylistItem,
} from '@nomercy-entertainment/nomercy-music-player';

// Real CC-licensed tracks from nomercy-media. Swap for your own content.
const items: MusicPlaylistItem[] = [
{
id: 'bent-wyre-01',
name: 'Ants Of The Beat',
url: '/B/bent%20wyre/%5B2025%5D%20If%20Only%20Life%20Was%20This%20Easy%20Volume%205%20-%20The%20Beat%20Misdirect/01%20Ants%20Of%20The%20Beat.mp3',
cover:
'/B/bent%20wyre/%5B2025%5D%20If%20Only%20Life%20Was%20This%20Easy%20Volume%205%20-%20The%20Beat%20Misdirect/01%20Ants%20Of%20The%20Beat.jpg',
artist: 'bent wyre',
},
{
id: 'bent-wyre-02',
name: 'Beat of Trespass',
url: '/B/bent%20wyre/%5B2025%5D%20If%20Only%20Life%20Was%20This%20Easy%20Volume%205%20-%20The%20Beat%20Misdirect/02%20Beat%20of%20Trespass.mp3',
cover:
'/B/bent%20wyre/%5B2025%5D%20If%20Only%20Life%20Was%20This%20Easy%20Volume%205%20-%20The%20Beat%20Misdirect/02%20Beat%20of%20Trespass.jpg',
artist: 'bent wyre',
},
];

const config: MusicPlayerConfig = {
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Music',
playlist: items,
};

const player = nmMPlayer('main')
.addPlugin(AutoAdvancePlugin)
.addPlugin(MediaSessionPlugin)
.setup(config);

player.on('ready', () => {
player.item(0, { autoplay: true });
});

That is a working music player. The inline playlist: array is auto-queued during setup. AutoAdvancePlugin advances the queue when a track ends. MediaSessionPlugin wires lock screen and notification controls.

Play, pause, and transport

TypeScript
await player.play();
await player.pause();
await player.stop();
await player.togglePlayback();

await player.next();
await player.previous();
await player.restart();

All transport methods return Promise<void>. They are safe to call without awaiting if you don’t need to sequence work after them.

Queue management

TypeScript
// Replace the entire queue:
player.queue([track1, track2, track3]);

// Read the queue:
const tracks = player.queue(); // ReadonlyArray<T>

// Append:
player.queueAppend(track4);

// Prepend (play next):
player.queuePrepend(track4);

// Remove by id:
player.queueRemove('4');

// Move a track:
player.queueMove(fromIndex, toIndex);

// Jump to a track:
player.item(track2);

// Read current:
const currentTrack = player.item(); // T | undefined

Volume

TypeScript
player.volume(80); // 0-100
const vol = player.volume(); // read
player.mute();
player.unmute();
player.toggleMute();
player.volumeUp(5); // raise by 5 percentage points (default is 5)
player.volumeDown(5); // lower by 5 percentage points

Shuffle and repeat

TypeScript
import { ShuffleState, RepeatState } from '@nomercy-entertainment/nomercy-music-player';

player.shuffleState(ShuffleState.ON);
player.shuffleState(ShuffleState.OFF);

player.repeatState(RepeatState.OFF);
player.repeatState(RepeatState.ONE);
player.repeatState(RepeatState.ALL);

Seeking

TypeScript
player.time(30); // seek to 30 seconds
const pos = player.time(); // read position
const dur = player.duration(); // total duration

player.forward(10); // skip forward 10s
player.rewind(10); // skip back 10s
player.seekByPercentage(50); // jump to midpoint (0-100 scale)

Listening to events

TypeScript
player.on('current', ({ item, index }) => {
console.log('Now playing:', item.name, 'at index', index);
});

player.on('time', ({ time }) => {
updateProgressBar(time / player.duration());
});

player.on('play', () => {
/* started */
});
player.on('pause', () => {
/* paused */
});
player.on('ended', () => {
/* track finished */
});
player.on('ready', () => {
/* setup complete */
});

See Events for the full list and payload shapes.

Authentication

If your audio sources require an Authorization header:

TypeScript
const player = nmMPlayer('main').setup({
playlist: [
/* items */
],
auth: {
bearerToken: () => myAuth.getAccessToken(),
refreshOnUnauthenticated: async () => {
await myAuth.refresh();
},
},
});

player.on('ready', () => {
player.item(0, { autoplay: true });
});

The player injects Authorization: Bearer <token> on every HLS manifest and segment request. On a 401, it calls refreshOnUnauthenticated once and retries. On a 403, the error propagates, do not retry.

CDN (no bundler)

You can drop the music player onto any page without a build step. Point a <script> at the IIFE bundle and you get a nmMPlayer global. The bundle expects hls.js to be present as the Hls global, so load that first even if you only play plain audio files.

HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/hls.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@nomercy-entertainment/nomercy-music-player@beta/dist/nomercy-music-player.iife.js"></script>
<script>
var player = window.nmMPlayer('main').setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Music',
playlist: [
{
id: 'bent-wyre-01',
name: 'Ants Of The Beat',
url: '/B/bent%20wyre/%5B2025%5D%20If%20Only%20Life%20Was%20This%20Easy%20Volume%205%20-%20The%20Beat%20Misdirect/01%20Ants%20Of%20The%20Beat.mp3',
},
],
});

player.on('ready', function () {
player.item(0, { autoplay: true });
});
</script>

The IIFE bundle carries the core player only. Built-in plugins (media session, lyrics, equalizer, and the rest) are not bundled into it, so install via npm and use ESM when you need them.