Web Players (Standalone)

Integrate Studio DRM Standalone with your web player.

Studio DRM Standalone can be implemented with JW Player, dash.js, Shaka, and most other commercial players.

The following table lists the DRM solutions supported by each player.

Player FairPlay PlayReady Widevine
JW Player
dash.js
Shaka

To implement Studio DRM Standalone with another player, contact your player representative for assistance.



JW Player

JW Player is an industry leading HTML5 video player.

The vuplay-jwplayer repository demonstrates at a lower level how to integrate Studio DRM Standalone with JW Player.


DRM Implementation

(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}";

    // Please login to https://admin.vudrm.tech to generate a VUDRM token.
    var vudrmToken = "{your-vudrm-token}";

    // setup jwplayer, passing the stream URLs and DRM configurations.  
    jwplayer("vuplay-container").setup({
        "playlist": [{
            "sources": [{
                "file": dashStreamURL,
                "drm": {
                    "widevine": {
                        "url": "https://widevine-license.vudrm.tech/proxy",
                        "headers": [{
                            "name": "X-VUDRM-TOKEN",
                            "value": vudrmToken
                        }]
                    },
                    "playready": {
                        "url": "https://playready-license.vudrm.tech/rightsmanager.asmx",
                        "headers": [{
                            "name": "X-VUDRM-TOKEN",
                            "value": vudrmToken
                        }]
                    }
                }
            }, 
            {
                "file": hlsStreamURL,
                "drm": {
                    "fairplay": {
                        "certificateUrl": fairplayCertURL,
                        "processSpcUrl": function (initData) {
                            return "https://" + initData.split("skd://").pop();
                        },
                        "licenseRequestHeaders": [
                            {
                                "name": "Content-type",
                                "value": "arraybuffer"
                            },
                            {
                                "name": "X-VUDRM-TOKEN",
                                "value": vudrmToken
                            }
                        ]
                    }
                }
            }]
        }]
    });
})();


dash.js

As an initiative of the DASH Industry Forum, dash.js was established as a production quality framework for building video and audio players that play back MPEG-DASH content using client-side JavaScript libraries leveraging the Media Source Extensions API set as defined by the W3C.

The vuplay-dashjs repository demonstrates at a lower level how to integrate Studio DRM Standalone with dash.js.


Basic Setup

var streamUrl = "<your-stream-url>";
var vudrmToken = "<your-vudrm-token>";

var player = dashjs.MediaPlayer().create();

DRM Implementation

var playReadyLaUrl =
  "https://playready-license.vudrm.tech/rightsmanager.asmx?token=" +
  encodeURIComponent(vudrmToken);

player.setProtectionData({
  "com.microsoft.playready": {
    serverURL: playReadyLaUrl,
    httpRequestHeaders: {}
  }
});

player.attachSource(streamUrl);
var overrideKeySystemWidevine = function() {
  return {
    getInitData: function(cpData, kid) {
      this.kid = kid;
      if ("pssh" in cpData) {
        return BASE64.decodeArray(cpData.pssh.__text).buffer;
      }
      return null;
    },

    getLicenseRequestFromMessage: function(message) {
      var body = {
        token: vudrmToken,
        drm_info: Array.apply(null, new Uint8Array(message)),
        kid: this.kid
      };
      body = JSON.stringify(body);
      return body;
    }
  };
};

var overrideProtectionKeyController = function() {
  var parent = this.parent;

  return {
    getSupportedKeySystemsFromContentProtection: function(cps) {
      var cp, ks, ksIdx, cpIdx;
      var supportedKS = [];
      var keySystems = parent.getKeySystems();
      var cpsWithKeyId = cps.find(function(element) {
        return element.KID !== null;
      });

      if (cps) {
        for (ksIdx = 0; ksIdx < keySystems.length; ++ksIdx) {
          ks = keySystems[ksIdx];
          for (cpIdx = 0; cpIdx < cps.length; ++cpIdx) {
            cp = cps[cpIdx];
            if (cp.schemeIdUri.toLowerCase() === ks.schemeIdURI) {
              var initData = ks.getInitData(cp, cpsWithKeyId.KID);
              if (initData) {
                supportedKS.push({
                  ks: keySystems[ksIdx],
                  initData: initData
                });
              }
            }
          }
        }
      }
      return supportedKS;
    }
  };
};

var widevineLaUrl = "https://widevine-license.vudrm.tech/proxy";

player.setProtectionData({
  "com.widevine.alpha": {
    serverURL: widevineLaUrl,
    httpRequestHeaders: {}
  }
});

player.attachSource(streamUrl);


Shaka

Shaka Player is a JavaScript library for adaptive video streaming. It plays DASH content without browser plugins using MediaSource Extensions and Encrypted Media Extensions.

The vuplay-shaka repository demonstrates at a lower level how to integrate Studio DRM Standalone with Google's Shaka player.

Google's Shaka player can be used to playback MPEG-dash streams with Widevine and PlayReady encryption, or HLS with FairPlay.


DRM Implementation

The following example can be found in the vuplay-shaka repository.

(function () {
    // Set your mpeg dash stream url
    var mpegdashStreamUrl = "{mpeg-dash-stream-url}";

    // Set your HLS stream url
    var hlsStreamUrl = "{hls-stream-url}";

    // Set your fairplay certificate url
    var fairplayCertificateUrl = "{fairplay-certificate-url}";

    // Will get overridden with the one from the manifest but we have to set something otherwise shaka will complain!
    var fairplayLicenseServerUrl = "https://fairplay-license.vudrm.tech/license";

    // Please login to https://admin.vudrm.tech to generate a vudrm token.
    var vudrmToken = "{vudrm-token}";

    // A bit of hacky way to detect Safari but will do for demo purposes...
    var isSafari = (navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1);

    // Fetch the fairplay certificate used to generate the fairplay license request
    function getFairplayCertificate() {
        var certRequest = new XMLHttpRequest();
        certRequest.responseType = "arraybuffer";
        certRequest.open("GET", fairplayCertificateUrl, true);
        certRequest.onload = function (event) {
            if (event.target.status == 200) {
                loadPlayer(new Uint8Array(event.target.response));
            } else {
                var error = new Error("HTTP status: " + event.target.status + " when getting Fairplay Certificate.");
                onError(error);
            }
        };
        certRequest.send();
    }

    // Returns a shaka player config for use with mpeg-dash streams
    function getNonSafariPlayerConfig() {
        return {
            drm: {
                servers: {
                    "com.widevine.alpha": "https://widevine-license.vudrm.tech/proxy",
                    "com.microsoft.playready": "https://playready-license.vudrm.tech/rightsmanager.asmx"
                }
            }
        }
    }

    // returns a shaka player config for use with HLS streams
    function getSafariPlayerConfig(fairplayCertificate) {
        return {
            drm: {
                servers: {
                    "com.apple.fps.1_0": fairplayLicenseServerUrl
                },
                advanced: {
                    "com.apple.fps.1_0": {
                        serverCertificate: fairplayCertificate
                    }
                },
                initDataTransform: function (initData, initDataType) {
                    if (initDataType == "skd") {
                        // Set the Fairplay license server URL with the one from the HLS manifest
                        fairplayLicenseServerUrl = shaka.util.StringUtils.fromBytesAutoDetect(initData);
                        
                        // Create the initData for Fairplay
                        var contentId = fairplayLicenseServerUrl.split("/").pop();
                        var certificate = window.shakaPlayerInstance.drmInfo().serverCertificate;
                        return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, certificate);
                    } else {
                        return initData;
                    }
                }
            }
        }
    }

    function loadPlayer(fairplayCertificate) {
        // setup the shaka player and attach an error event listener
        var video = document.getElementById("video");
        window.shakaPlayerInstance = new shaka.Player(video);
        window.shakaPlayerInstance.addEventListener("error", onErrorEvent);

        // configure the DRM license servers
        var playerConfig = isSafari ? getSafariPlayerConfig(fairplayCertificate) : getNonSafariPlayerConfig();
        window.shakaPlayerInstance.configure(playerConfig);

        // Something special is needed for the widevine license request.
        window.shakaPlayerInstance
            .getNetworkingEngine()
            .registerRequestFilter(function (type, request) {
                // ignore requests that are not license requests.
                if (type != shaka.net.NetworkingEngine.RequestType.LICENSE)
                    return;

                // set the VUDRM token as a header on the license request
                request.headers["X-VUDRM-TOKEN"] = vudrmToken;

                // custom fairplay license request body required
                if (window.shakaPlayerInstance.drmInfo().keySystem == "com.apple.fps.1_0") {
                    request.headers["Content-Type"] = "ArrayBuffer"
                    request.uris = [fairplayLicenseServerUrl.replace("skd", "https")];
                }
            });

        // load the mpeg-dash or HLS stream into the shaka player
        window.shakaPlayerInstance
            .load(isSafari ? hlsStreamUrl : mpegdashStreamUrl)
            .then(function () {
                console.log("The stream has now been loaded!");
            })
            .catch(onError);
    }

    // Set polyfills required by shaka
    shaka.polyfill.installAll();
    // Check browser is supported and load the player.
    if (shaka.Player.isBrowserSupported()) {
        if (isSafari) {
            // Get the fairplay certificate, once the cert is retrieved then the player will be loaded.
            getFairplayCertificate();
        } else {
            loadPlayer();
        }
    } else {
        console.error("This browser does not have the minimum set of APIs needed for shaka!");
    }
})();

function onErrorEvent(event) {
    // Extract the shaka.util.Error object from the event.
    onError(event.detail);
}

function onError(error) {
    console.error("Error code", error.code, "object", error);
}