DRM
DrmPlugin handles EME (Encrypted Media Extensions) license acquisition for Widevine, FairPlay, and PlayReady protected streams.
Register it when your media requires DRM.
It probes for EME support at startup, emits 'unsupported' and exits cleanly in environments without it (JSDOM, SSR), and coordinates the key-system handshake when the active playlist item carries a drm field.
Plugin id
'drm'
Import
import { DrmPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import type { DrmOptions, DrmEvents } from '@nomercy-entertainment/nomercy-video-player/plugins';
What it does
When use() runs, the plugin checks that requestMediaKeySystemAccess exists to confirm EME is available in this environment.
If the API is missing, it emits 'unsupported' and returns without registering any listeners.
Once EME is confirmed present, the plugin subscribes to the player’s 'current' event.
Whenever the active item has a drm field, it calls requestMediaKeySystemAccess with the item’s key system to verify reachability.
If that probe fails, it emits 'key:error'.
fetchLicense() is available for explicit license retrieval.
It routes the request through customSignRequest (for HMAC or proprietary signing) and applies transformLicenseRequest / transformLicenseResponse when provided.
Internally it uses the core’s this.fetch helper, so it inherits the player’s auth and retry configuration.
Options
| Option | Type | Default | Description |
|---|---|---|---|
keySystem | string | required | Key system ID. See the table below. |
licenseUrl | string | required | License server endpoint. |
certificate | ArrayBuffer | string | undefined | Service certificate. Required for FairPlay, optional for others. |
customSignRequest | (request: Request) => Request | Promise<Request> | undefined | Signs the license request before it is sent (HMAC, custom headers). |
transformLicenseRequest | (challenge: ArrayBuffer) => ArrayBuffer | Promise<ArrayBuffer> | undefined | Transforms the challenge body before it is sent to the license server. |
transformLicenseResponse | (response: ArrayBuffer) => ArrayBuffer | Promise<ArrayBuffer> | undefined | Transforms the license bytes received from the server before they are used. |
hdcpRequired | 'type-0' | 'type-1' | 'none' | undefined | Minimum HDCP output protection level. |
Key system strings
| DRM system | keySystem value |
|---|---|
| Widevine | 'com.widevine.alpha' |
| FairPlay | 'com.apple.fps' |
| PlayReady | 'com.microsoft.playready' |
Events
| Event | Payload | Description |
|---|---|---|
'key:error' | { sessionId: string; error: Error } | License acquisition or key-system probe failed. |
'unsupported' | { reason: string } | EME not available in this environment. Plugin exits cleanly. |
Methods
fetchLicense
plugin.fetchLicense(challenge: ArrayBuffer): Promise<ArrayBuffer>
Fetches a license blob from the configured licenseUrl.
Applies transformLicenseRequest to the challenge before sending and transformLicenseResponse to the response bytes before returning.
When customSignRequest is provided, the plugin builds a Request object, runs it through the signer, and forwards the resulting URL and headers.
The underlying HTTP call uses the core’s this.fetch helper, not the platform fetch directly.
mediaKeys
plugin.mediaKeys(): MediaKeys | null
Returns the MediaKeys instance currently bound to the video element, or null when EME is unsupported in this environment, when no video element is present, or when the browser’s mediaKeys property is null.
Registration
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import type { VideoPlaylistItem } from '@nomercy-entertainment/nomercy-video-player';
import { DrmPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
// DrmPlugin reads item.drm at runtime via an internal type cast.
// VideoPlaylistItem has no drm field, so extend it for your own items:
interface DrmVideoItem extends VideoPlaylistItem {
drm?: { keySystem?: string; initData?: ArrayBuffer };
}
const player = nmplayer<DrmVideoItem>('player')
.addPlugin(DrmPlugin, {
keySystem: 'com.widevine.alpha',
licenseUrl: 'https://api.example.com/license/widevine',
})
.setup({
playlist: [
{
id: 'protected-1',
title: 'Protected content',
url: 'https://api.example.com/stream/protected.m3u8',
drm: { keySystem: 'com.widevine.alpha' },
},
],
});
player.on('plugin:drm:key:error', ({ sessionId, error }) => {
console.error('Key error for session', sessionId, error);
});
player.on('plugin:drm:unsupported', ({ reason }) => {
console.warn('DRM not available:', reason);
});