Radiant Media Player

Working with VUDRM by Vualto



Guide sections


Scope of support

VUDRM by VUALTO is a popular DRM service provider. Radiant Media Player is compatible with VUDRM technology to reliably deliver content with DASH with both Widevine and PlayReady DRM. Apple FairPlay Streaming is also supported. You can review our compatibility table for DRM with DASH streaming here.

This documentation will guide on how to easily implement VUDRM with Radiant Media Player.

VUALTO is a Radiant Media Player technology alliance partner.


DASH with Widevine and PlayReady DRM

First, you will need an account with VUDRM and to prepare your content for DASH streaming with Widevine and PlayReady DRM. Radiant Media Player will take care of loading and parsing the DASH manifest, contacting the DRM licensing servers and displaying content when authorised. Our DASH streaming & DRM implementation is based on Shaka player. Documentation for DASH streaming with Radiant Media Player can be found here. Documentation for using DRM with Radiant Media Player can be found here. Below you will find a complete example for using VUDRM with Radiant Media Player.

<script src="https://cdn.radiantmediatechs.com/rmp/5.0.8/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  // DASH streaming URL
  var src = {
    dash: 'https://your-dash-url.mpd'
  };
  // VUDRM token
  var vudrmToken = 'vu-drm-token';
  // license server for PlayReady
  var playReadyLaURL = 'https://playready-license.drm.technology/rightsmanager.asmx?token=' + encodeURIComponent(vudrmToken);
  // license server for Widevine
  var widevineLaURL = 'https://widevine-proxy.drm.technology/proxy';

  // create Radiant Media Player instance
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);

  // custom DRM filter for Radiant Media Player to properly access VUDRM licensing servers
  var shakaCustomRequestFilter = function (type, request) {

    // ignore requests that are not license requests
    if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) return;

    // get shaka player instance from Radiant Media Player
    var shakaPlayerInstance = rmp.shakaPlayer;
    if (!shakaPlayerInstance) {
      return;
    }

    // get the selected drm info and check the key system is widevine
    var selectedDrmInfo = shakaPlayerInstance.drmInfo();
    if (selectedDrmInfo.keySystem !== "com.widevine.alpha") {
      return;
    }
    // select the first key id and convert to uppercase as it is hex
    var keyId = selectedDrmInfo.keyIds[0].toUpperCase();

    // create the license request body required by the license server
    var body = {
      "token": vudrmToken,
      "drm_info": Array.apply(null, new Uint8Array(request.body)),
      "kid": keyId
    };
    body = JSON.stringify(body);

    // set the request body
    request.body = body;

    // add the content type header
    request.headers["Content-Type"] = "application/json";
  };
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    poster: 'https://your-poster-url.jpg',
    // here we pass our custom DRM data
    shakaDrm: {
      servers: {
        "com.widevine.alpha": widevineLaURL,
        "com.microsoft.playready": playReadyLaURL
      }
    },
    shakaCustomRequestFilter: shakaCustomRequestFilter
  };
  rmp.init(settings);
</script>

Apple FairPlay streaming (FPS)

We also support FairPlay streaming with VUDRM to Radiant Media Player. FairPlay streaming, which requires HLS, aims at providing support for DRM encrypted content to Apple devices, for us this macOS Safari 9+ and Safari for iOS 11.2+. More information about FPS support in Radiant Media Player can be found here.

<script src="https://cdn.radiantmediatechs.com/rmp/5.0.8/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  // FPS streaming URL (HLS)
  var src = {
    fps: 'your-fps-url.m3u8'
  };
  // VUDRM token
  var vudrmToken = 'vu-drm-token';
  // license server for FPS
  var certificatePath = 'https://fairplay-license.drm.technology/certificate';
  // certificate server for FPS
  var processSpcPath = 'https://fairplay-license.drm.technology/license';
  // the following are specific player settings so that VUDRM FPS implementation
  // can work in Radiant Media Player
  var licenseResponseType = 'arraybuffer';
  
  var contentId = null;
  var extractContentId = function (initData) {
    var arrayToString = function (array) {
      var uint16array = new Uint16Array(array.buffer);
      return String.fromCharCode.apply(null, uint16array);
    };
    var rawContentId = arrayToString(initData);
    var tmp = rawContentId.split('/');
    contentId = tmp[tmp.length - 1];
    return contentId;
  };
  
  var licenseRequestLoaded = function (event) {
    if (event && event.target) {
      var request = event.target;
      if (typeof request.status === 'number' && request.status === 200 && request.session && request.response) {
        var session = request.session;
        var key = new Uint8Array(request.response);
        session.update(key);
      }
    }
  };
  
  var base64EncodeUint8Array = function (input) {
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input[i++];
      chr2 = i < input.length ? input[i++] : Number.NaN;
      chr3 = i < input.length ? input[i++] : Number.NaN;

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }
      output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    }
    return output;
  };
  
  var licenseRequestMessage = function (keyMessage) {
    var body = {
      "token": vudrmToken,
      "contentId": contentId,
      "payload": base64EncodeUint8Array(keyMessage)
    };
    return JSON.stringify(body);
  };
  
  var licenseRequestHeaders = [
    {
      name: 'Content-type',
      value: 'application/json'
    }
  ];

  var certificateRequestHeaders = [
    {
      name: 'x-vudrm-token',
      value: vudrmToken
    }
  ];

  // passing our player settings
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    poster: 'https://your-poster-url.jpg',
    fpsDrm: {
      certificatePath: certificatePath,
      certificateRequestHeaders: certificateRequestHeaders,
      processSpcPath: processSpcPath,
      licenseResponseType: licenseResponseType,
      licenseRequestHeaders: licenseRequestHeaders,
      extractContentId: extractContentId,
      licenseRequestLoaded: licenseRequestLoaded,
      licenseRequestMessage: licenseRequestMessage
    }
  };

  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);
  rmp.init(settings);
</script>

Maximizing device reach with FPS + DASH DRM

In real life case scenario, it is likely you will want to use a combination of DASH with Widevine and PlayReady DRM and FPS DRM to maximise device reach. When you provide both DASH DRM and FPS DRM data to Radiant Media Player it will automatically detect which is supported for the targeted device and use the related DRM information to playback content securely.

<script src="https://cdn.radiantmediatechs.com/rmp/5.0.8/js/rmp.min.js"></script>
<div id="rmpPlayer"></div>
<script>
  // DASH + FPS streaming URL (HLS)
  var src = {
    dash: 'https://your-dash-url.mpd',
    fps: 'https://your-fps-url.m3u8'
  };
  // VUDRM token: in this case we assume the same token can be used for DASH and FPS DRM
  var vudrmToken = 'vu-drm-token';

  // license server for PlayReady
  var playReadyLaURL = 'https://playready-license.drm.technology/rightsmanager.asmx?token=' + encodeURIComponent(vudrmToken);
  // license server for Widevine
  var widevineLaURL = 'https://widevine-proxy.drm.technology/proxy';
  
  // create Radiant Media Player instance
  var elementID = 'rmpPlayer';
  var rmp = new RadiantMP(elementID);

  // custom DRM filter for Radiant Media Player to properly access VUDRM licensing servers
  var shakaCustomRequestFilter = function (type, request) {

    // ignore requests that are not license requests
    if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) return;

    // get shaka player instance from Radiant Media Player
    var shakaPlayerInstance = rmp.shakaPlayer;
    if (!shakaPlayerInstance) {
      return;
    }

    // get the selected drm info and check the key system is widevine
    var selectedDrmInfo = shakaPlayerInstance.drmInfo();
    if (selectedDrmInfo.keySystem !== "com.widevine.alpha") {
      return;
    }
    // select the first key id and convert to uppercase as it is hex
    var keyId = selectedDrmInfo.keyIds[0].toUpperCase();

    // create the license request body required by the license server
    var body = {
      "token": vudrmToken,
      "drm_info": Array.apply(null, new Uint8Array(request.body)),
      "kid": keyId
    };
    body = JSON.stringify(body);

    // set the request body
    request.body = body;

    // add the content type header
    request.headers["Content-Type"] = "application/json";
  };

  // license server for FPS
  var certificatePath = 'https://fairplay-license.drm.technology/certificate';
  // certificate server for FPS
  var processSpcPath = 'https://fairplay-license.drm.technology/license';
  // the following are specific player settings so that VUDRM FPS implementation
  // can work in Radiant Media Player
  var licenseResponseType = 'arraybuffer';
  
  var contentId = null;
  var extractContentId = function (initData) {
    var arrayToString = function (array) {
      var uint16array = new Uint16Array(array.buffer);
      return String.fromCharCode.apply(null, uint16array);
    };
    var rawContentId = arrayToString(initData);
    var tmp = rawContentId.split('/');
    contentId = tmp[tmp.length - 1];
    return contentId;
  };
  
  var licenseRequestLoaded = function (event) {
    if (event && event.target) {
      var request = event.target;
      if (typeof request.status === 'number' && request.status === 200 && request.session && request.response) {
        var session = request.session;
        var key = new Uint8Array(request.response);
        session.update(key);
      }
    }
  };
  
  var base64EncodeUint8Array = function (input) {
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input[i++];
      chr2 = i < input.length ? input[i++] : Number.NaN;
      chr3 = i < input.length ? input[i++] : Number.NaN;

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }
      output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    }
    return output;
  };
  
  var licenseRequestMessage = function (keyMessage) {
    var body = {
      "token": vudrmToken,
      "contentId": contentId,
      "payload": base64EncodeUint8Array(keyMessage)
    };
    return JSON.stringify(body);
  };
  
  var licenseRequestHeaders = [
    {
      name: 'Content-type',
      value: 'application/json'
    }
  ];

  var certificateRequestHeaders = [
    {
      name: 'x-vudrm-token',
      value: vudrmToken
    }
  ];

  // passing our player settings
  var settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    poster: 'https://your-poster-url.jpg',
    // here we pass our custom FPS DRM data
    fpsDrm: {
      certificatePath: certificatePath,
      certificateRequestHeaders: certificateRequestHeaders,
      processSpcPath: processSpcPath,
      licenseResponseType: licenseResponseType,
      licenseRequestHeaders: licenseRequestHeaders,
      extractContentId: extractContentId,
      licenseRequestLoaded: licenseRequestLoaded,
      licenseRequestMessage: licenseRequestMessage
    },
    // here we pass our custom DASH DRM data
    shakaDrm: {
      servers: {
        "com.widevine.alpha": widevineLaURL,
        "com.microsoft.playready": playReadyLaURL
      }
    },
    shakaCustomRequestFilter: shakaCustomRequestFilter
  };
  rmp.init(settings);
</script>
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.