Documentation

Working with PallyCon

Scope of support

PallyCon provides 360 degree Cloud-based End-to-End Content Security. Radiant Media Player is compatible with PallyCon technology to reliably deliver content with DASH Widevine/PlayReady DRM and Apple FairPlay Streaming. You can review our compatibility table for DRM with DASH or HLS streaming here.

This documentation will guide you on how to easily implement PallyCon DRM solution with Radiant Media Player.

PallyCon is a Radiant Media Player technology alliance partner.

DASH with Widevine and PlayReady DRM

First, you will need an account with PallyCon 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. General documentation for DASH streaming with Radiant Media Player can be found here. General documentation for using DRM with Radiant Media Player can be found here. Below you will find a complete example for using PallyCon with Radiant Media Player.

<script src="https://cdn.radiantmediatechs.com/rmp/7.11.5/js/rmp.min.js"></script>
<div id="rmp"></div>
<script>
  // PallyCon license server URL
  const licenseUri = 'https://pallycon-license-server-url/licenseManager.do';
  // Widevine DRM token
  const widevineToken = 'pallycon-widevine-drm-token';
  // PlayReady DRM token
  const playreadyToken = 'pallycon-playready-drm-token';
  // Input DASH stream
  const src = {
    dash: 'https://your-dash-url.mpd'
  };
  // We need to test what DRM is supported (Widevine first, PlayReady second)
  // Based on the result of that detection we will init the player with the correct DRM token
  const config = [{
    "initDataTypes": ["cenc"],
    "audioCapabilities": [{
      "contentType": "audio/mp4;codecs=\"mp4a.40.2\""
    }],
    "videoCapabilities": [{
      "contentType": "video/mp4;codecs=\"avc1.42E01E\""
    }]
  }];
  const initPlayer = function (input) {
    const settings = {
      licenseKey: 'your-license-key',
      src: src,
      width: 640,
      height: 360,
      contentMetadata: {
        poster: [
          'https://your-poster-url.jpg'
        ]
      }
    };
    if (input === 'widevine') {
      settings.shakaDrm = {
        servers: {
          "com.widevine.alpha": licenseUri
        }
      };
      settings.shakaRequestConfiguration = {
        license: {
          headers: {
            'pallycon-customdata-v2': widevineToken
          }
        }
      };
    } else {
      settings.shakaDrm = {
        servers: {
          "com.microsoft.playready": licenseUri
        }
      };
      settings.shakaRequestConfiguration = {
        license: {
          headers: {
            'pallycon-customdata-v2': playreadyToken
          }
        }
      };
    }
    const elementID = 'rmp';
    const rmp = new RadiantMP(elementID);
    rmp.init(settings);
  };

  const checkPlayReadySupport = function () {
    navigator.
      requestMediaKeySystemAccess("com.microsoft.playready", config).
      then(mediaKeySystemAccess => {
        console.log('PlayReady DRM is supported');
        initPlayer('playready');
      }).catch(e => {
        console.log('PlayReady DRM is NOT supported');
        console.log(e);
      });
  };

  const checkWidevineSupport = function () {
    if (typeof navigator.requestMediaKeySystemAccess === 'function') {
      navigator.
        requestMediaKeySystemAccess("com.widevine.alpha", config).
        then(mediaKeySystemAccess => {
          console.log('Widevine DRM is supported');
          initPlayer('widevine');
        }).catch(e => {
          console.log('Widevine DRM is NOT supported - checking for PlayReady DRM');
          console.log(e);
          checkPlayReadySupport();
        });
    } else {
      console.log('Missing requestMediaKeySystemAccess support');
    }
  };
  checkWidevineSupport();
</script>

Apple FairPlay streaming (FPS)

We also support FairPlay streaming with PallyCon to Radiant Media Player. FairPlay streaming, which requires HLS, aims at providing support for DRM encrypted content to Apple devices. For us this is macOS Safari 11+, Safari for iOS 12+ and iPadOS 13+, iOS 13+ and iPadOS 13+ WKWebView. More information about FPS support in Radiant Media Player can be found here.

<script src="https://cdn.radiantmediatechs.com/rmp/7.11.5/js/rmp.min.js"></script>
<div id="rmp"></div>
<script>
  const licenseUri = 'https://pallycon-license-server-url/licenseManager.do';
  const fairplayCertUri = 'https://pallycon-certificate-server-url/fpsKeyManager.do?siteId=ZZZZZZ';
  const fairplayToken = 'pallycon-fairplay-drm-token';
  const src = {
    fps: 'https://fps-hls-url.m3u8'
  };
  // we define our functions and variables to be passed to the player
  // this is specific to FairPlay streaming with PallyCon
  // extractContentId
  const arrayToString = function (array) {
    const uint16array = new Uint16Array(array.buffer);
    return String.fromCharCode.apply(null, uint16array);
  };
  const extractContentId = function (initData) {
    const contentId = arrayToString(initData);
    return contentId.substring(contentId.indexOf('skd://') + 6);
  };
  // licenseRequestHeaders
  const licenseRequestHeaders = [
    {
      name: 'pallycon-customdata-v2',
      value: fairplayToken
    },
    {
      name: 'Content-type',
      value: 'application/x-www-form-urlencoded'
    }
  ];
  // prepareCertificate
  const prepareCertificate = function (rawResponse) {
    const responseText = String.fromCharCode.apply(null, new Uint8Array(rawResponse));
    const raw = window.atob(responseText);
    const rawLength = raw.length;
    const certificate = new Uint8Array(new ArrayBuffer(rawLength));
    for (let i = 0; i < rawLength; i++) {
      certificate[i] = raw.charCodeAt(i);
    }
    return certificate;
  };
  // init player
  const settings = {
    licenseKey: 'your-license-key',
    src: src,
    width: 640,
    height: 360,
    contentMetadata: {
      poster: [
        'https://your-poster-url.jpg'
      ]
    },
    fpsDrm: {
      certificatePath: fairplayCertUri,
      prepareCertificate: prepareCertificate,
      processSpcPath: licenseUri,
      licenseRequestHeaders: licenseRequestHeaders,
      extractContentId: extractContentId
    }
  };
  const elementID = 'rmp';
  const 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/7.11.5/js/rmp.min.js"></script>
<div id="rmp"></div>
<script>
  // PallyCon license server URL
  const licenseUri = 'https://pallycon-license-server-url/licenseManager.do';
  // Widevine DRM token
  const widevineToken = 'pallycon-widevine-drm-token';
  // PlayReady DRM token
  const playreadyToken = 'pallycon-playready-drm-token';
  // Input DASH stream
  const src = {
    dash: 'https://your-dash-url.mpd'
  };
  // We need to test what DRM is supported (Widevine first, PlayReady second)
  // Based on the result of that detection we will init the player with the correct DRM token
  const config = [{
    "initDataTypes": ["cenc"],
    "audioCapabilities": [{
      "contentType": "audio/mp4;codecs=\"mp4a.40.2\""
    }],
    "videoCapabilities": [{
      "contentType": "video/mp4;codecs=\"avc1.42E01E\""
    }]
  }];
  
  // FPS data
  const fairplayLicenseUri = 'https://pallycon-license-server-url/licenseManager.do';
  const fairplayCertUri = 'https://pallycon-certificate-server-url/fpsKeyManager.do?siteId=ZZZZZZ';
  const fairplayToken = 'pallycon-fairplay-drm-token';
  src.fps = 'https://fps-hls-url.m3u8';
  const arrayToString = function (array) {
    const uint16array = new Uint16Array(array.buffer);
    return String.fromCharCode.apply(null, uint16array);
  };
  const extractContentId = function (initData) {
    const contentId = arrayToString(initData);
    return contentId.substring(contentId.indexOf('skd://') + 6);
  };
  const licenseRequestHeaders = [
    {
      name: 'pallycon-customdata-v2',
      value: fairplayToken
    },
    {
      name: 'Content-type',
      value: 'application/x-www-form-urlencoded'
    }
  ];
  const prepareCertificate = function (rawResponse) {
    const responseText = String.fromCharCode.apply(null, new Uint8Array(rawResponse));
    const raw = window.atob(responseText);
    const rawLength = raw.length;
    const certificate = new Uint8Array(new ArrayBuffer(rawLength));
    for (let i = 0; i < rawLength; i++) {
      certificate[i] = raw.charCodeAt(i);
    }
    return certificate;
  };

  const initPlayer = function (input) {
    const settings = {
      licenseKey: 'your-license-key',
      src: src,
      width: 640,
      height: 360,
      fpsDrm: {
        certificatePath: fairplayCertUri,
        prepareCertificate: prepareCertificate,
        processSpcPath: fairplayLicenseUri,
        licenseRequestHeaders: licenseRequestHeaders,
        extractContentId: extractContentId
      },
      contentMetadata: {
        poster: [
          'https://your-poster-url.jpg'
        ]
      }
    };
    if (input === 'widevine') {
      settings.shakaDrm = {
        servers: {
          "com.widevine.alpha": licenseUri
        }
      };
      settings.shakaRequestConfiguration = {
        license: {
          headers: {
            'pallycon-customdata-v2': widevineToken
          }
        }
      };
    } else if (input === 'playready') {
      settings.shakaDrm = {
        servers: {
          "com.microsoft.playready": licenseUri
        }
      };
      settings.shakaRequestConfiguration = {
        license: {
          headers: {
            'pallycon-customdata-v2': playreadyToken
          }
        }
      };
    }
    const elementID = 'rmp';
    const rmp = new RadiantMP(elementID);
    rmp.init(settings);
  };

  const checkPlayReadySupport = function () {
    navigator.
      requestMediaKeySystemAccess("com.microsoft.playready", config).
      then(mediaKeySystemAccess => {
        console.log('PlayReady DRM is supported');
        initPlayer('playready');
      }).catch(e => {
        console.log('PlayReady DRM is NOT supported - trying FairPlay streaming');
        console.log(e);
        initPlayer('fps');
      });
  };

  const checkWidevineSupport = function () {
    if (typeof navigator.requestMediaKeySystemAccess === 'function') {
      navigator.
        requestMediaKeySystemAccess("com.widevine.alpha", config).
        then(mediaKeySystemAccess => {
          console.log('Widevine DRM is supported');
          initPlayer('widevine');
        }).catch(e => {
          console.log('Widevine DRM is NOT supported - checking for PlayReady DRM');
          console.log(e);
          checkPlayReadySupport();
        });
    } else {
      console.log('Missing requestMediaKeySystemAccess support');
    }
  };
  checkWidevineSupport();
</script>
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License.

©2015-2022 Radiant Media Player. All Rights Reserved.