Skip to content

Commit

Permalink
feat: allow reuse of persistent license sessions (shaka-project#4461)
Browse files Browse the repository at this point in the history
Add capability to re-use persistent license sessions across sessions.

DrmEngine will now always:
- try to start stored persistent sessions before trying to fetch a
license, as-to be able to check if all needed keys are already loaded.
- ask for a new license when the persistent session doesn't have the
needed keys for playback,

Given the flag `persistentSessionOnlinePlayback` is true, DrmEngine:
- won't remove the persistent session from the device at the end of the
playback,
- won't throw an error when the persistent session isn't found on the
device,

For now, it needs Shaka's users to persist session information by
themselves (localStorage, IndexDB, ...) before giving it back for the
next session. Still, it lays foundation to develop the feature to fully
handling it on Shaka's side.

Related to shaka-project#1956
  • Loading branch information
valotvince committed Apr 19, 2023
1 parent 6937325 commit cc97da1
Show file tree
Hide file tree
Showing 10 changed files with 488 additions and 48 deletions.
61 changes: 61 additions & 0 deletions docs/tutorials/drm-config.md
Expand Up @@ -208,3 +208,64 @@ you should provide an empty string as robustness
##### Other key-systems

Values for other key systems are not known to us at this time.

#### Re-use persistent license DRM for online playback

If your DRM provider configuration allows you to deliver persistent license,
you could re-use the created MediaKeys session for the next online playback.

Configure Shaka to start DRM sessions with the `persistent-license` type
instead of the `temporary` one:

```js
player.configure({
drm: {
advanced: {
'com.widevine.alpha': {
'sessionType': 'persistent-license'
}
}
}
});
```

**Using `persistent-license` might not work on every devices, use this feature
carefully.**

When the playback starts, you can retrieve the sessions metadata:

```js
const activeDrmSessions = this.player.getActiveSessionsMetadata();
const persistentDrmSessions = activeDrmSessions.filter(
({ sessionType }) => sessionType === 'persistent-license');

// Add your own storage mechanism here, give it an unique known identifier for
// the playing video
```

When starting the same video again, retrieve the metadata from the storage, and
set it back to Shaka's configuration.

Shaka will load the given DRM persistent sessions and will only request a
license if some keys are missing for the content.

```js
player.configure({
drm: {
persistentSessionOnlinePlayback: true,
persistentSessionsMetadata: [{
sessionId: 'deadbeefdeadbeefdeadbeefdeadbeef',
initData: new InitData(0),
initDataType: 'cenc'
}]
}
});
```

NB: Shaka doesn't provide a out-of-the-box storage mechanism for the sessions
metadata.

#### Continue the Tutorials

Next, check out {@tutorial license-server-auth}.
Or check out {@tutorial fairplay}.
55 changes: 55 additions & 0 deletions externs/shaka/player.js
Expand Up @@ -681,12 +681,60 @@ shaka.extern.ProducerReferenceTime;
shaka.extern.AdvancedDrmConfiguration;


/**
* @typedef {{
* sessionId: string,
* sessionType: string,
* initData: ?Uint8Array,
* initDataType: ?string
* }}
*
* @description
* DRM Session Metadata for an active session
*
* @property {string} sessionId
* Session id
* @property {string} sessionType
* Session type
* @property {?Uint8Array} initData
* Initialization data in the format indicated by initDataType.
* @property {string} initDataType
* A string to indicate what format initData is in.
* @exportDoc
*/
shaka.extern.DrmSessionMetadata;


/**
* @typedef {{
* sessionId: string,
* initData: ?Uint8Array,
* initDataType: ?string
* }}
*
* @description
* DRM Session Metadata for saved persistent session
*
* @property {string} sessionId
* Session id
* @property {?Uint8Array} initData
* Initialization data in the format indicated by initDataType.
* @property {?string} initDataType
* A string to indicate what format initData is in.
* @exportDoc
*/
shaka.extern.PersistentSessionMetadata;


/**
* @typedef {{
* retryParameters: shaka.extern.RetryParameters,
* servers: !Object.<string, string>,
* clearKeys: !Object.<string, string>,
* delayLicenseRequestUntilPlayed: boolean,
* persistentSessionOnlinePlayback: boolean,
* persistentSessionsMetadata:
* !Array.<shaka.extern.PersistentSessionMetadata>,
* advanced: Object.<string, shaka.extern.AdvancedDrmConfiguration>,
* initDataTransform:
* ((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
Expand All @@ -713,6 +761,13 @@ shaka.extern.AdvancedDrmConfiguration;
* <i>Defaults to false.</i> <br>
* True to configure drm to delay sending a license request until a user
* actually starts playing content.
* @property {boolean} persistentSessionOnlinePlayback
* <i>Defaults to false.</i> <br>
* True to configure drm to try playback with given persistent session ids
* before requesting a license. Also prevents the session removal at playback
* stop, as-to be able to re-use it later.
* @property {!Array.<PersistentSessionMetadata>} persistentSessionsMetadata
* Persistent sessions metadata to load before starting playback
* @property {Object.<string, shaka.extern.AdvancedDrmConfiguration>} advanced
* <i>Optional.</i> <br>
* A dictionary which maps key system IDs to advanced DRM configuration for
Expand Down

0 comments on commit cc97da1

Please sign in to comment.