Studio DRM with JW Platform and Chromecast

Integrate Studio DRM with your JW Platform and Chromecast

The Google Cast framework enables a viewer to stream content to a compatible TV or sound system. By enabling the Google Cast framework in your app, a viewer can use a cast button to stream your content to a Cast-enabled device on a shared network.

This article explains two integrations:

  • Enabling the Google Cast framework for the JW web player
  • Casting video content protected by Studio DRM with the JW Platform

📘

VUDRM was rebranded as Studio DRM following JW Player’s acquisition of Vualto. Any references to VUDRM in this document or in the Studio DRM Admin portal refer to Studio DRM.



Requirements

Integrating Studio DRM with JW Platform and Chromecast has several requirements.

Item Notes
Application Registration Registration allows you to test your custom receiver. Specifically, you will be able to connect to the custom receiver with your custom Cast implementation.
Cast App A Cast app enables DRM-protected content to be streamed on a Cast-enabled device.

A Cast app consists of two components:
  • Sender app
  • Receiver app
You can use the JW Player Chromecast Custom Receiver Demo App to guide your implementation.

NOTE: Google recommends installing a mix of http-server and ngrok to deploy your receiver locally.
Content URLs Through a signed URL, the license URL and streaming URL for each media ID are retrieved.

Use the following steps to retrieve the content URLs:
  1. Use this sample code to generate the signed URL.
  2. Make a GET call with the signed URL.
  3. From the API response, extract the license and streaming URLs from the following parameters:
    • playlist[].sources.drm.widevine.url (license)
    • playlist[].sources.drm.file (streaming)

// Signed URL response - Delivery API sample
{
   "title":"Sintel.2010.1080p",
   "kind":"Single Item",
   "playlist":[
      {
         ...
         "sources":[
            {
               "drm":{
                  "widevine":{
                     "url":"<widevine-license-url>"
                  },
                  ...
               },
               "file":"<dash-stream-url>",
               "type":"application/dash+xml"
            },
            ...
         ]
      }
   ],
   ...
}


Configure the Cast app

For DRM playback, you must configure both components of the Cast app.


Receiver app

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Studio DRM Custom Chromecast Receiver</title>
    <link rel="stylesheet" href="main.css" media="screen" />
    <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

<body>
    <cast-media-player></cast-media-player>
</body>
<footer>
    <script src="receiver.js"></script>
</footer>
</html>

  1. In the receiver.js file of the receiver app, define playbackConfig.licenseUrl with the signed Widevine license URL.

    📘

    The signed license URL for the receiver app must be generated with the same parameters as the signed license URL for the sender app:

    • Media ID
    • v1 API Secret
    • DRM Policy ID

    When needed, URLs should be generated separately to avoid expiration before casting begins.

(() => {
    const context = cast.framework.CastReceiverContext.getInstance();
    const playerManager = context.getPlayerManager();

    playerManager.setPlaybackConfig(createPlaybackConfig(playerManager));
    context.start();

    function createPlaybackConfig(playerManager) {
        let playbackConfig = (Object.assign(new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
        playbackConfig.licenseUrl = '<widevine-license-url>';
        playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
        return playbackConfig;
    }
})();

Sender app

  1. In the sender app index.html file, add your signed streaming and license URLs:
    • Define stream with your signed DASH streaming URL.
    • Define laurl with the signed Widevine license URL.
<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Studio DRM Sender App</title>
    <script src="./cast-service.js"></script>
    <script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
</head>

<body>
    <google-cast-launcher></google-cast-launcher>
    <button id="play">Play</button>
    <script>
        let castService;
        window['__onGCastApiAvailable'] = function (isAvailable) {
            if (isAvailable) {
                const stream = "<dash-stream-url>";
                const laurl = "<widevine-license-url>";
                castService = new CastService(stream, laurl);
                castService.initCast();
            }
        };
    </script>
</body>
</html>
  1. In the cast-service.js file, define receiverApplicationId with your registered Cast receiver app ID.
const CastService = function (stream, laurl) {
    this._context;
    this._laurl = laurl
    this._mimeType = 'application/dash+xm';
    this._remotePlayer;
    this._remotePlayerController;
    this._stream = stream;
}

CastService.prototype.initCast = function () {
    this._context = cast.framework.CastContext.getInstance();
    this._context.setOptions({
        receiverApplicationId: '<your-receiver-application-id>',
        autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
    });

    this._remotePlayer = new cast.framework.RemotePlayer();
    this._remotePlayerController = new cast.framework.RemotePlayerController(this._remotePlayer);
    this._remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
        () => { this.connectionHandler(); },
        false
    );
    
    document.getElementById('play').addEventListener('click', this.play.bind(this));
}

  
CastService.prototype.connectionHandler = function () {
    if (!this._remotePlayer.isConnected) return;
    let mediaInfo = new chrome.cast.media.MediaInfo(this._stream, this._mimeType);
  
    mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
    mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
    mediaInfo.metadata.title = 'Studio DRM Receiver Demo';
    mediaInfo.customData = { laurl: this._laurl};

    let request = new chrome.cast.media.LoadRequest(mediaInfo);
    let session = this._context.getCurrentSession();
    session.loadMedia(request);
}

CastService.prototype.play = function () {
    this._remotePlayerController.playOrPause();
}


Enable casting for a viewer

Once you set up your custom receiver, you will be able to cast DRM content from the JW web player. For reference, you may see our Studio DRM integration with JW Player.

  1. Add the cast object to your setup.
  2. In the JW Player studiodrm-jwplayer.js file, define dash-stream-url with your signed streaming URL.
  3. Define widevine-license-url with the signed license URL.
  4. Define your-receiver-application-id with your registered custom receiver app ID from the Google Cast developer console.
(function() {

    // Set the mpeg-dash stream URL.
    var dashStreamURL = "<dash-stream-url>"

    // Set the hls stream URL.
    var hlsStreamURL = "<hls-stream-url>";

    // Set the URL to retrieve the fairplay certificate from.
    var fairplayCertURL = "<fairplay-cert-url>";

    // setup jwplayer, passing the stream URLs and DRM configurations.
    jwplayer("studiodrm-container").setup({
        "playlist": [{
            "sources": [{
                "file": dashStreamURL,
                "drm": {
                    "widevine": {
                        "url": "<widevine-license-url>"
                    },
                    "playready": {
                        "url": "https://playready-license.vudrm.tech/rightsmanager.asmx",
                    }
                }
            },
            {
                "file": hlsStreamURL,
                "drm": {
                    "fairplay": {
                        "certificateUrl": fairplayCertURL,
                        "processSpcUrl": function (initData) {
                            return "https://" + initData.split("skd://").pop();
                        },
                        "licenseRequestHeaders": [
                            {
                                "name": "Content-type",
                                "value": "arraybuffer"
                            }
                        ]
                    }
                }
            }]
        }],
        "cast": {
            "appid": "<your-receiver-application-id>"
        }
    });
})();

You can now cast DRM-protected video content onto a Chromecast device.



FAQ

How do I implement Airplay with DRM media?

Airplay will automatically be implemented by the Apple OS with DRM Media.

📘

NOTE: If an Airplay session is initiating after 10 minutes or longer of playback on the sending device, playback on the receiving device will fail. The user will need to restart the video in the Airplay session. This occurs because the Airplay receiver is using the existing authorization which has timed out.