Persistent DRM licenses

Storing a DRM license lets you reuse it later — for example, for offline playback. This page covers persistent-license support by DRM system, storing and removing licenses, and customizing where session data lives.

To store or load an offline session, provide an offlineId in the DRM configuration. Use the asset ID or any other stable identifier. If the player finds a stored session for that offlineId, it loads the session for playback. If no stored session is found, the SDK requests the license and stores it for later use.

Support

Persistent-license support depends on the DRM system, the browser, and your DRM or license-server setup. Your integration must support persistent-license workflows end to end.

Widevine

Widevine persistent and offline licenses are no longer supported on Chromium-based browsers.

PlayReady

PlayReady persistent licenses are supported when the browser and your license server configuration support them.

FairPlay

FairPlay persistent licenses are not supported.

DRMtoday

For DRMtoday, persistent-license support also depends on your License Policy, formerly the Customer Rights Token (CRT).

Import the persistent module

import "@castlabs/prestoplay/cl.persistent";

Store a license during playback

const player = new clpp.Player({...});

player.on(clpp.events.DRM_SESSION_PERSISTED, function (e) {
  console.log(e);
});

// The license is fetched and stored on the first `load` call and
// reused for subsequent `load` calls.
player.open({
  source: {
    url: 'https://demo.cf.castlabs.com/media/bbb_abr/Manifest.mpd',
    type: clpp.Type.DASH
  },
  drm: {
    env: 'DRMtoday_STAGING',
    customData: {
      userId: 'purchase',
      sessionId: 'p0',
      merchant: 'six',
    },
    offlineId: 'abcxyz'
  },
  ...
});

Store a license without a player instance

You can also store a license without creating a player instance. Use persistent.fetchLicense and pass the source — either as a string or as a Source — together with the DRM configuration.

try {
  await clpp.persistent.fetchLicense('//example.com/manifest.mpd',
    {
      env: 'DRMtoday_STAGING',
      customData: {
        userId: 'purchase',
        sessionId: 'p0',
        merchant: 'six',
      },
      offlineId: 'abcxyz'
    },
  );
  console.log('Success!');
} catch (e) {
  console.error('Couldn\'t fetch license', e);
}

Remove a stored license

Remove a stored license you no longer need with clpp.persistent.removeLicense():

const offlineId = 'abcxyz'

await clpp.persistent.removeLicense(offlineId);

Session storage

Loading an offline DRM session requires additional metadata. When a license is persisted, the SDK also stores session IDs, the server certificate, and other related data — see persistent.SessionInfo.

PRESTOplay includes a built-in storage engine that uses the window.localStorage API to store and load this session information.

To use a different storage API, such as IndexedDB, implement the persistent.ISessionStorage interface and pass it to the SDK with clpp.persistent.useStorage():

/**
 * Custom storage implementation.
 */
class MySessionStorage {
  /**
   * @param {string} offlineId
   * @param {clpp.persistent.SessionInfo} sessionInfo
   * @return {Promise}
   */
  store (offlineId, sessionInfo) {
    ...
  }

  /**
   * @param {string} offlineId
   * @return {Promise<clpp.persistent.SessionInfo>}
   */
  get (offlineId) {
    ...
  }

  /**
   * @param {string} offlineId
   * @return {Promise}
   */
  delete (offlineId) {
    ...
  }

  /**
   * @return {Promise}
   */
  clear () {
    ...
  }

  /**
   * @return {string}
   */
  getName () {
    return 'MySessionStorage'
  }
}

clpp.persistent.useStorage(new MySessionStorage());

const player = new clpp.Player({...});

...

player.open({
  source: {...},
  drm: {
    offlineId: 'abcxyz',
    ...
  }
});
Previous topic: DRM