API
DRM

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:

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 or loadingRequest.request.url?.host
  • loadedLicenseUrl: The URL retrieved from loadingRequest.request.URL.absoluteString, starting with skd:// or clearkey://
  • licenseServer: The URL passed in the DRM object
  • spcString: 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));
  }
}
We are TheWidlarzGroupPremium support →