Entitlement and DRM
What you learn
You're instantiating DIVA Player in your web front-end and relying on Third Party Video Production as the video streaming source.
The goal of this article is to build the simplest front-end to stream a video with entitlement check and DRM.
Before starting
- Ensure the video production you rely on is up and running.
- Set the videoId and
<stream URL>. - Ensure to set the
entitlementProviderproperty when initializing DIVA, respecting the following interfaces:
Instantiation
Entitlement configuration
In order to enable the entitlement check, you need to set the entitlementProvider property when initializing DIVA.
DIVA will call the getConfiguration method to get the configuration and the request method to perform the entitlement request in the right moment.
entitlementProvider is an object that implements the EntitlementProvider interface.
...
export type EntitlementProvider = {
getConfiguration: (cb: (cf: EntitlementConfiguration) => void) => void;
request: (request: EntitlementRequest) => Promise<EntitlementSuccessResponse>;
};
export interface EntitlementConfiguration {
heartBeatInterval: number;
heartbeatSeekInterval?: number;
}
export interface EntitlementRequest {
type: EntitlementRequestType;
videoMetadata: VideoMetadataClean;
videoSource: VideoSourceClean;
offsetFromLiveEdge?: number;
}
export type EntitlementRequestType = 'processUrl' | 'heartBeat';
export const EntitlementRequestType = {
processUrl: 'processUrl' as EntitlementRequestType,
heartBeat: 'heartBeat' as EntitlementRequestType,
};
export interface EntitlementSuccessResponse {
contentUrl: string;
drmData: {
licenseUrl: string;
token?: string;
headers?: { key: string; value: string }[];
};
playbackSessionId?: string;
trackingUrl?: string;
heartBeatInterval: number;
}
Data resiliency
For v3 entitlement flows, the /videos tokenization call does not send Authorization. If the response body returns a SessionToken, DIVA stores it and uses it only on subsequent /videos/heartbeat requests as Authorization. Each heartbeat response can return a new SessionToken, and DIVA replaces the stored value for the next heartbeat. If no token is returned, DIVA omits Authorization, so v2 behavior stays unchanged. Retry handling covers HTTP 408 and 429 responses through the configured retries value.
Entitlement code sample
// DIVA Player SDK
import { DivaWebComponent } from "@deltatre-vxp/diva-sdk/diva-web-sdk";
import type { DivaConfiguration, VideoMetadata, VideoMetadataClean } from "@deltatre-vxp/diva-sdk/diva-web-sdk";
// Import SDK style
import "@deltatre-vxp/diva-sdk/diva-web-sdk/index.min.css";
const libs = {
mux: "https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js",
shaka: "https://ajax.googleapis.com/ajax/libs/shaka-player/4.16.15/shaka-player.compiled.js",
hlsJs: "https://cdn.jsdelivr.net/npm/hls.js@1.5.7",
googleIMA: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
googleDAI: 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js',
googleCast: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1',
threeJs: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.148.0/three.min.js',
};
const config: DivaConfiguration = {
videoId: "<video id>",
libs: libs,
setting: {
general: {
culture: 'en-GB',
}
},
dictionary: {
messages: {},
},
videoMetadataProvider: async (
videoId: string,
currentVideoMetadata?: VideoMetadataClean,
playbackState?: {
chromecast?: boolean | undefined;
}): Promise<VideoMetadata> => {
return {
"title": "Video Title",
"sources": [
{
"uri": "<stream URL>",
"format": "HLS"
}
],
"videoId": "<video id>",
};
},
entitlementProvider: {
getConfiguration: () => {
return {
heartBeatInterval: 30000,
heartbeatSeekInterval: 10000
}
},
request: async (request: EntitlementRequest): Promise<EntitlementSuccessResponse> => {
// Call the entitlement service (usually asynchronous)
return {
contentUrl: "<tokenized stream URL>",
drmData: {
licenseUrl: "<license URL>",
token: "<token>",
headers: [{ key: "<key>"; value: "<value>" }]
},
heartBeatInterval: 30000
};
}
}
};
export const App = () => {
return <DivaWebComponent config={config} />;
};