JWP Web Player (JW Platform)
Learn how to configure your player to generate a license request and authenticate your video playback using a valid streaming key from the license server.
If you are not utilizing Studio DRM with JW Platform please reference these guides based on your use case:
- Studio DRM Standalone with JW Web Player if using Studio DRM Standalone
- The DRM Configuration Option in JW Web Player if using another vendor’s DRM
JWP provides a simplified approach to protecting1 your content with industry-standard Digital Rights Management (DRM). By enabling DRM on a property from your JWP dashboard, the complex aspects of DRM management are managed by JWP on your behalf:
- Several configured DRM Policies
- DRM media content key generation and management for FairPlay Streaming
- License delivery services for content playback on any Apple device
With JWP managing the technical aspects of DRM, you can focus on the design and implementation of engaging content experiences. For more information about the DRM workflow, please refer to the High-Level Workflow Overview.
1 Studio DRM blocks recording via browser extensions/add-ons or certain software programs on the application level, but is not guaranteed for all web browsers. Blocking screen recording depends on the Content Decryption Module (CDM) used in the browser. The CDM may vary with browsers updates and versions.
For the following use cases, use Studio DRM Standalone with your current streaming and hosting solution:
- Choosing not to enable Studio DRM with JW Platform
- Implementing live stream integrations
Compatibility
The two most recent stable versions of the following listed browsers are supported.
HTML5 Browsers | FairPlay | PlayReady | Widevine |
---|---|---|---|
Chrome | ✓ |
||
Firefox | ✓ |
||
Internet Explorer 11 (Windows 8.1+) |
✓ |
||
Microsoft Edge (Windows 10+) |
✓ |
✓ |
|
Opera | ✓ |
||
Safari | ✓ |
Requirements
Item | Notes |
---|---|
DRM entitlement | Contact your JWP representative for more information. |
DRM-enabled property | See: Enable a property |
FairPlay Streaming Deployment Package | See: Add FairPlay credentials to a property |
Embedded player | See: Add a player library |
Implementation
Use the following steps to set up DRM playback in your web player:
-
Generate a signed URL for DRM playback.
-
Make a
GET
call with the signed URL. Within thesources
array of the API response, the content URL with its associated DRM-specific LAURLs are returned.Both the media URL and its associated LAURLs are valid for only 10 minutes from when they are requested. When a multi-item playlist of DRM-protected media is provided to the player, an intermediary service must be used to retrieve valid LAURLs for each media.
curl -L -X GET 'https://cdn.jwplayer.com/v2/media/{media_id}/drm/{policy_id}?token={valid_JWT}' \ - H 'Authorization: Bearer {v2_api_secret}'
"sources": [{ "drm": { "widevine": { "url": "Widevine LAURL" }, "playready": { "url": "Playready LAURL" } }, "file": "MPD-URL.mpd", "type": "application/dash+xml" }, { "drm": { "fairplay": { "processSpcUrl": "FairPlay LAURL", "certificateUrl": "FairPlay Certificate URL" } }, "file": "M3U8-URL.m3u8", "type": "application/vnd.apple.mpegurl" } ]
-
In the
jwplayer().setup()
, create a playlist[].sources[] object in which you define DASH and HLS streams for the same content.
The following example includes the following streams: DASH and HLS.jwplayer('myElement').setup({ "playlist": [{ "sources": [{ "file": "MPD-URL.mpd", "type": "application/dash+xml" }, { "file": "M3U8-URL.m3u8" "type": "application/vnd.apple.mpegurl" }] }] });
-
For each file (
playlist[].sources[].file
), add the LAURLs into a drm object.jwplayer('myElement').setup({ "playlist": [ { "sources": [ { "drm": { "widevine": { "url": "Widevine LAURL" }, "playready": { "url": "Playready LAURL" } }, "file": "MPD-URL.mpd", "type": "application/dash+xml" }, { "drm": { "fairplay": { "processSpcUrl": "FairPlay LAURL", "certificateUrl": "FairPlay Certificate URL" } }, "file": "M3U8-URL.m3u8", "type": "application/vnd.apple.mpegurl" } ], "tracks": [ { "kind": "captions", "file": "https://www.yourdomain.com/caption-file_en.vtt", "label": "English" }, { "kind": "captions", "file": "https://www.yourdomain.com/caption-file_sp.vtt", "label": "Español" } ] } ] });
Intermediary Service
One way to playback multi-item playlists is to set up an intermediary service that can generate the signed URL mentioned above and make the GET
request to the Delivery API. The service will then return the relevant LAURLs and content URLs as they are needed by the player.
This intermediary service should use an appropriate form of authentication to prevent exposing the ability to retrieve valid content URLs and the LAURLs needed to achieve playback.
Once you have an intermediary service setup the player can be initialized as below.
Each playlist item requires both a valid media ID and
drm
section to be defined. The actual values in thedrm
object are not important. They will be replaced just before each piece of content is loaded with signed links retrieved from the intermediary service.
jwplayer("player").setup({
"playlist": [{
"title": "DRM Item 1",
"mediaId": "mediaId1",
"sources": [{
"drm": {
"widevine": {
"url": "https://temp.com"
},
"playready": {
"url": "https://temp.com"
}
},
"file": "https://temp.mpd",
"type": "application/dash+xml"
},{
"drm": {
"fairplay": {
"processSpcUrl": "https://temp.com",
"certificateUrl": "https://temp.com"
},
},
"file": "https://temp.m3u8",
"type": "application/vnd.apple.mpegurl"
}]
},{
"title": "DRM Item 2",
"mediaId": "mediaId2",
"sources": [{
"drm": {
"widevine": {
"url": "https://temp.com"
},
"playready": {
"url": "https://temp.com"
}
},
"file": "https://temp.mpd",
"type": "application/dash+xml"
},{
"drm": {
"fairplay": {
"processSpcUrl": "https://temp.com",
"certificateUrl": "https://temp.com"
},
},
"file": "https://temp.m3u8",
"type": "application/vnd.apple.mpegurl"
}]
}]
});
With this initialization, you can then use the setPlaylistItemCallback method to update each playlist item before it is loaded with the relevant signed URL.
The following functions require two global variables:
policyId
set to a valid policy IDurlServiceHost
set to the host DNS of the intermediary service
jwplayer().setPlaylistItemCallback(function(item, index) {
return new Promise(function(resolve, reject) {
updatePlaylistItem(item);
resolve(item);
});
});
function updatePlaylistItem(item) {
if (item.sources[0].type == "dash") {
item.file = getManifestUrl("mpd", item.mediaId, policyId);
item.sources[0].drm = {
widevine: {
url: getLaurl("widevine", item.mediaId, policyId)
},
playready: {
url: getLaurl("playready", item.mediaId, policyId)
}
}
} else {
item.file = getManifestUrl("m3u8", item.mediaId, policyId);
item.sources[0].drm = {
fairplay: {
processSpcUrl: getLaurl("fairplay", item.mediaId, policyId, "/laurl"),
certificateUrl: getLaurl("fairplay", item.mediaId, policyId, "/cert")
}
}
}
item.sources[0].file = item.file;
}
function getLaurl(drm, mediaId, policyId, fairplayPostfix="") {
console.log("getting laurl for " + mediaId);
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", `${urlServiceHost}/${drm}/${mediaId}/${policyId}${fairplayPostfix}`, false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
function getManifestUrl(type, mediaId, policyId) {
console.log("getting manifest for " + mediaId);
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", `${urlServiceHost}/${type}/${mediaId}/${policyId}`, false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
Updated 5 months ago