DRM
DRM Example
We provide a sample implementation in the example app (opens in a new tab) demonstrating how to use DRM with react-native-video
. You’ll need a valid token—visit our site (opens in a new tab) to obtain a free 24-hour token.
DRM Offline
If you need DRM-protected content available offline, our Offline Video SDK (opens in a new tab) enables downloading, storing, and managing streams with and without DRM. It also handles many edge cases you may encounter over time.
Prerequisites:
- Use
react-native-video
v6 or v7. If you're still on v5 or lower, contact us (opens in a new tab) for assistance.
Supporting our software kits helps maintain this open-source project. Thank you!
Providing DRM Data (Tested with HTTP/HTTPS Assets)
You can configure DRM playback by providing a DRM object with the following properties. This feature disables the use of TextureView
on Android.
DRM Properties
base64Certificate
Platforms: iOS | visionOS
Type: boolean
Default: false
Indicates whether the certificate URL returns data in Base64 format.
certificateUrl
Platforms: iOS | visionOS
Type: string
Default: undefined
The URL used to fetch a valid certificate for FairPlay.
getLicense
Platforms: iOS | visionOS
Type: function
Default: undefined
Instead of setting licenseServer
, you can manually acquire the license in JavaScript and send the result to the native module for FairPlay DRM configuration.
The following parameters are available in getLicense
:
contentId
: The content ID from the DRM object orloadingRequest.request.url?.host
loadedLicenseUrl
: The URL retrieved fromloadingRequest.request.URL.absoluteString
, starting withskd://
orclearkey://
licenseServer
: The URL passed in the DRM objectspcString
: The SPC used for DRM validation
You should return a Base64-encoded CKC response, either directly or as a Promise
.
Example:
getLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {
const base64spc = Base64.encode(spcString);
const formData = new FormData();
formData.append('spc', base64spc);
return fetch(`https://license.pallycon.com/ri/licenseManager.do`, {
method: 'POST',
headers: {
'pallycon-customdata-v2': 'your-custom-header',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
})
.then((response) => response.text())
.then((response) => response)
.catch((error) => console.error('Error', error));
};
contentId
Platforms: iOS | visionOS
Type: string
Default: undefined
Sets the content ID for the stream. If not specified, the system uses the host value from loadingRequest.request.URL.host
.
headers
Platforms: Android | iOS | visionOS
Type: Object
Default: undefined
Custom headers for the license server request.
Example:
drm: {
type: DRMType.WIDEVINE,
licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
headers: {
'X-AxDRM-Message': 'your-drm-header',
},
}
licenseServer
Platforms: Android | iOS | visionOS
Type: string
Default: undefined
The license server URL that authorizes protected content playback.
multiDrm
Platform: Android
Type: boolean
Default: false
Indicates whether the DRM system should support key rotation. See Android Developer Docs (opens in a new tab) for more details.
type
Platforms: Android | iOS
Type: DRMType
Default: undefined
Defines the DRM type:
- Android:
DRMType.WIDEVINE
,DRMType.PLAYREADY
,DRMType.CLEARKEY
- iOS:
DRMType.FAIRPLAY
localSourceEncryptionKeyScheme
Platforms: iOS | visionOS
Type: string
Sets the URL scheme for stream encryption keys used in local assets.
Example:
localSourceEncryptionKeyScheme="my-offline-key"
Common Usage Scenarios
Sending Cookies to the License Server
You can send cookies using the headers
prop.
Example:
drm: {
type: DRMType.WIDEVINE,
licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
headers: {
'Cookie': 'PHPSESSID=your-session-id; csrftoken=mytoken; _gat=1; foo=bar'
},
}
Custom License Acquisition (iOS Only)
Example:
drm: {
type: DRMType.FAIRPLAY,
getLicense: (spcString) => {
const base64spc = Base64.encode(spcString);
return fetch('YOUR_LICENSE_SERVER_URL', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
getFairplayLicense: {
foo: 'bar',
spcMessage: base64spc,
}
})
})
.then(response => response.json())
.then((response) => {
if (response?.getFairplayLicenseResponse?.ckcResponse) {
return response.getFairplayLicenseResponse.ckcResponse;
}
throw new Error('No valid response');
})
.catch((error) => console.error('CKC error', error));
}
}