Skip to content

DrmPlugin

If you need to play Widevine, FairPlay, or PlayReady protected audio streams, DrmPlugin is where that support will live. The plugin is exported in v2.0 so you can inspect the error and the public surface is already reserved for the integration. Full EME key system coordination ships in v2.1.

TypeScript
import { DrmPlugin } from '@nomercy-entertainment/nomercy-music-player/plugins';
import type { DrmOptions, DrmEvents } from '@nomercy-entertainment/nomercy-music-player/plugins';

Plugin id: 'music-drm'

Do not register this plugin in production while it remains a stub.

What it does

DrmPlugin is a forward-reserved stub. Its DrmOptions and DrmEvents interfaces define the full v2.1 contract so you can write type-safe integration code against them today. When use() is called, the plugin throws NotImplementedError with the message 'DrmPlugin: roadmapped for v2.1. Not available in v2.0.'. addPlugin() catches that throw internally, calls dispose(), and emits plugin:failed on the player. The exception never propagates to the caller. dispose() is a no-op in the stub.

Options

These options are defined in the source as the v2.1 contract. None of them are read in v2.0 because use() throws before any option is consumed.

OptionTypeDefaultDescription
keySystemstringrequiredEME key system identifier, e.g. 'com.widevine.alpha', 'com.apple.fps', 'com.microsoft.playready'.
licenseUrlstringrequiredLicense server URL.
certificateArrayBuffer | stringundefinedService certificate for FairPlay. Optional for Widevine and PlayReady.
customSignRequest(request: Request) => Request | Promise<Request>undefinedRequest signer for license calls, e.g. HMAC or token injection.
transformLicenseRequest(challenge: ArrayBuffer) => ArrayBuffer | Promise<ArrayBuffer>undefinedLicense request body transformer.
transformLicenseResponse(response: ArrayBuffer) => ArrayBuffer | Promise<ArrayBuffer>undefinedLicense response body transformer.

Events

These events are defined in DrmEvents and reserved for v2.1. The stub does not emit any of them.

EventPayloadDescription
key:requested{ sessionId: string; initData: ArrayBuffer }EME key session was created and a license request was sent.
key:granted{ sessionId: string }License granted, decryption is active.
key:expired{ sessionId: string }Key session expired.
key:revoked{ sessionId: string }Key session was revoked.
key:error{ sessionId: string; error: Error }License acquisition failed.
output:restricted{ reason: string }HDCP or output protection policy blocked playback.
unsupported{ reason: string }The key system is not supported in this environment.

Consumer event listeners use the plugin:<id>:<event> prefix form:

TypeScript
player.on('plugin:music-drm:key:granted', ({ sessionId }) => {
console.log('DRM ready, session', sessionId);
});

Registration

The plugin class is exported so your type-checking and introspection code compiles today. Because addPlugin() absorbs the NotImplementedError and emits plugin:failed, use a plugin:failed listener to detect and handle the stub error rather than a try/catch.

TypeScript
import nmMPlayer from '@nomercy-entertainment/nomercy-music-player';
import { DrmPlugin } from '@nomercy-entertainment/nomercy-music-player/plugins';

const player = nmMPlayer('main')
.addPlugin(DrmPlugin, {
keySystem: 'com.widevine.alpha',
licenseUrl: 'https://api.example.com/drm/license',
})
.setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Music',
playlist: [
{
id: 'kjc-01',
name: 'Thaw You Out',
url: '/D/Derek%20Clegg/%5B2010%5D%20KJC/01%20Thaw%20You%20Out.mp3',
artist: 'Derek Clegg',
},
],
});

// addPlugin() catches NotImplementedError internally and emits plugin:failed.
// No exception propagates to the caller -- listen here to detect the stub.
player.on('plugin:failed', ({ id, error }) => {
if (id === 'music-drm') {
console.warn('DRM not available in v2.0:', error.message);
}
});

See also