This guide covers how to configure DRM (Digital Rights Management) settings in Vinyl for both player-level and track-level configurations.
Configure DRM settings at the player level for default behavior across all tracks:
import { createVinylPlayer, DrmKeySystem, DrmRobustness } from '@amzn/vinyl'
createVinylPlayer({
media: new Audio(),
drm: {
keySystems: {
[DrmKeySystem.WIDEVINE]: {
licenseServer: async () => {
return {
url: 'https://cwip-shaka-proxy.appspot.com/no_auth',
init: {
headers: { Authorization: await getAuthToken() },
},
}
},
video: {
// Default is SW_SECURE_CRYPTO (L3), may be changed to HW_SECURE_ALL (L1) on devices with support.
robustness: DrmRobustness.HW_SECURE_ALL,
},
audio: {
robustness: DrmRobustness.HW_SECURE_ALL,
},
priority: 1,
},
[DrmKeySystem.PLAY_READY]: {
licenseServer: {
url: 'http://test.playready.microsoft.com/service/rightsmanager.asmx',
},
},
},
},
})
You can configure a wildcard ('*') key system that will be used as a fallback
when no specific key system matches. This is useful for providing default DRM
settings that apply to any unrecognized key systems.
import { createVinylPlayer, DrmKeySystem, DrmRobustness } from '@amzn/vinyl'
createVinylPlayer({
media: new Audio(),
drm: {
keySystems: {
[DrmKeySystem.WIDEVINE]: {
licenseServer: {
url: 'https://widevine-license-server.com/license',
},
},
// Wildcard fallback for any other key systems
'*': {
licenseServer: {
url: 'https://generic-license-server.com/license',
},
video: {
robustness: DrmRobustness.SW_SECURE_CRYPTO,
},
audio: {
robustness: DrmRobustness.SW_SECURE_CRYPTO,
},
},
},
},
})
DRM has 3 possible tiers of security:
L1 (Level 1) - HW_SECURE_ALL - L1 DRM offers the highest level of
security for content protection. This tier typically involves both the
decryption of media content and the execution of DRM code within a secure
hardware environment, such as a Trusted Execution Environment (TEE). L1
requires hardware-based security features. The decryption and processing of
media content occur in a secure, isolated part of the hardware, preventing
exposure to the operating system or software layers.
L2 (Level 2) - HW_SECURE_CRYPTO, HW_SECURE_DECODE - L2 DRM provides a
middle ground between security and flexibility. In this tier, the DRM code
may still execute in a secure environment, but media decryption can happen in
the software layer, although still within a protected memory region. This
tier offers a compromise between robust security and broader device
compatibility.
L3 (Level 3) - SW_SECURE_CRYPTO, SW_SECURE_DECODE - L3 DRM is the
most basic security tier, where both the DRM code execution and media
decryption occur entirely in software, without relying on hardware-based
security. No special hardware security features are required, and all
operations are handled in the application and operating system software
layers.
Tracks can override DRM settings on a per-track basis using the drm property
in track load options. This allows customizing license providers, key systems,
and other DRM settings for individual tracks.
import { createVinylPlayer, DrmKeySystem } from '@amzn/vinyl'
const player = createVinylPlayer({ media: new Audio() })
player.load({
type: 'dash',
uri: 'https://example.com/encrypted-track.mpd',
drm: {
licenseProvider: async (keySystem, serverOptions, challenge) => {
// Custom license provider logic
// To change request options such as url or request parameters,
// a custom license provider isn't needed; see licenseServer
// configuration
const response = await fetch(serverOptions.url, {
method: 'POST',
body: challenge,
headers: { 'Content-Type': 'application/octet-stream' },
})
return response.arrayBuffer()
},
keySystems: {
[DrmKeySystem.WIDEVINE]: {
licenseServer: {
url: 'https://custom-license-server.com/widevine',
init: {
headers: { Authorization: 'Bearer token123' },
},
},
},
},
},
})
License server configuration supports three ValueProvider formats:
Direct Value: Provide the configuration object directly
import { DrmKeySystemOptions } from '@amzn/vinyl'
const options: DrmKeySystemOptions = {
licenseServer: {
url: 'https://license-server.com/endpoint',
init: { headers: { Authorization: 'Bearer token' } },
},
}
Synchronous Function: Return configuration from a function
import { DrmKeySystemOptions } from '@amzn/vinyl'
const options: DrmKeySystemOptions = {
licenseServer: () => ({
url: getConfiguredLicenseUrl(),
init: { headers: { Authorization: getCurrentToken() } },
}),
}
Async Function: Return a Promise resolving to configuration
import { DrmKeySystemOptions } from '@amzn/vinyl'
const options: DrmKeySystemOptions = {
licenseServer: async () => {
const token = await fetchAuthToken()
return {
url: 'https://license-server.com/endpoint',
init: { headers: { Authorization: `Bearer ${token}` } },
}
},
}
When a manifest is parsed, representations are filtered out if they do not
contain a supported key system (DrmController.isSupported). If content is
encrypted with multiple key systems supported by the system, the one chosen will
be prioritized first by the priority value in the configuration (higher values
take precedence, default priority is 0), then by the existence of a set
licenseServer configuration, and lastly by the order found within the
manifest.
Dash manifests contains content protection elements with scheme ids. These are
resolved to key system(s) by a key system resolver
(schemeIdUri: string) => readonly DrmKeySystem[] which may be changed by
overriding the drmKeySystemResolver dependency when constructing a player. The
default resolver provides all known key systems for the given scheme.
Vinyl does not yet support persistent licenses.
Web playback does not support group licenses; every track must have its own license.