HLS + Playready content is not working

Hello,

I’m not able to reproduce a HLS content with Playready DRM and I decided to create a POC from scratch, based on the DRM Content Playback LG documentation, in order to investigate it step by step. It seems that this content is not able to play even in very basic application based on your documentation. I receive all logs saying “success” for the load DRM certificate, sending DRM messages and load video, without no errors, but the video doesn’t play. If I try to play a content without DRM it works fine. Also, this content with DRM is working in other manunfacturer devices.

I’m attaching the image with the results:

index.js

let url = 'https://8572e342e3eeb5c4.mediapackage.us-east-1.amazonaws.com/out/v1/ed6bd28952a347d8bf8c981fca10d416/index.m3u8';
// let url = 'https://82934cf9c8696bd2.mediapackage.us-east-1.amazonaws.com/out/v1/f8d12b8d09674de28c0fca3e6e726c65/dashOutput.mpd';
let drmServerUrl = 'https://lic.drmtoday.com/license-proxy-headerauth/drmtoday/RightsManager.asmx';
let customData = 'eyJ1c2VySWQiOiJwdXJjaGFzZSIsInNlc3Npb25JZCI6ImthdWUtc2Vzc2lvbiIsIm1lcmNoYW50Ijoic2J0In0=';

let drmType = 'playready';
var appId = 'com.sbtplus.sbtctv';
var msgType = "application/vnd.ms-playready.initiator+xml";
var drmSystemId = "urn:dvb:casystemid:19219";
var clientId;
var isDrmClientLoaded;
var subscriptionHandler;

let MIME_TYPE = {
  DASH: 'application/dash+xml',
  HLS: 'application/x-mpegurl',
  HLS_ALT: 'application/vnd.apple.mpegurl',
  MP4: 'video/mp4',
  SMOOTH_STREAMING: 'application/vnd.ms-sstr+xml'
};
let mimeType = MIME_TYPE.HLS;

var options = {};
options.option = {};
options.option.drm = {};
options.option.drm.type = drmType;
options.option.drm.clientId = clientId;

var mediaOption = encodeURIComponent(JSON.stringify(options));
var msgId = ''

var msg = '<?xml version="1.0" encoding="utf-8"?>' +
'<PlayReadyInitiator xmlns= "http://schemas.microsoft.com/DRM/2007/03/protocols/">' +
'<LicenseAcquisition>' +
    '<Header>' +
      '<WRMHEADER xmlns= "http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0">' +
        '<DATA>' +
          '<PROTECTINFO>' +
            '<KEYLEN>16</KEYLEN>' +
            '<ALGID>AESCTR</ALGID>' +
          '</PROTECTINFO>' +
          '<LA_URL>'+ drmServerUrl +'</LA_URL>' +
          '<KID>lFmb2gxg0Cr5bfEnJXgJeA==</KID>' +
          '<CHECKSUM>P7ORpD2IpA==</CHECKSUM>' +
        '</DATA>' +
      '</WRMHEADER>' +
    '</Header>' +
    '<CustomData>' + customData + '</CustomData>' +
  '</LicenseAcquisition>' +
'</PlayReadyInitiator>'

// Define DRM Type

function checkIfClientIsLoaded() {
    var request = webOS.service.request("luna://com.webos.service.drm", {
        method: "isLoaded",
        parameters: {
            "appId": appId
        },
        onSuccess: function (inResponse) {
					console.log("Result: " + JSON.stringify(inResponse));
					sendRightInformation();
					subscribeLicensingError();
        },
        onFailure: function (inError) {
					console.log("Failed to get DRM client loading state");
					console.log("[" + inError.errorCode + "]: " + inError.errorText);
					// To-Do something
					return;
        }
    }
    );
}

function loadDrmClient() {
  var request = webOS.service.request('luna://com.webos.service.drm', {
    method: 'load',
    parameters: {
      drmType: drmType,
      appId: appId,
    },
    onSuccess: function (result) {
      clientId = result.clientId;
      isDrmClientLoaded = true;
      console.log('DRM Client is loaded successfully.');
      checkIfClientIsLoaded();
    },
    onFailure: function (result) {
      console.log('[' + result.errorCode + '] ' + result.errorText);
      // Do something for error handling
    },
  });
}

function sendRightInformation() {
  console.log('clientId', clientId);
  console.log('msgType', msgType);
  console.log('msg', msg);
  console.log('drmSystemId', drmSystemId);

  request = webOS.service.request("luna://com.webos.service.drm", {
    method:"sendDrmMessage",
    parameters: {
      clientId: clientId,
      msgType: msgType,
      msg: msg,
      drmSystemId: drmSystemId
    },
    onSuccess: function (result) {
      msgId = result.msgId;
      var resultCode = result.resultCode;
      var resultMsg = result.resultMsg;
      console.log("Message ID: " + msgId);
      console.log("[" + resultCode + "] " + resultMsg);

      if (resultCode != 0){
          // Do Handling DRM message error
      }
      playVideo(url);
    },
    onFailure: function (result) {
        console.log("[" + result.errorCode + "] " + result.errorText);
    }
  });
}

function subscribeLicensingError() {
  var request = webOS.service.request("luna://com.webos.service.drm", {
    method:"getRightsError",
    parameters: {
      "clientId": clientId,
      "subscribe": true
    },
    onSuccess: function (result) { // Subscription Callback
      contentId = result.contentId;
      if (contentId == msgId) {
        if ( 0 == result.errorState) {
          console.log("No license");
          // Do something for error handling
        }
        else if ( 1 == result.errorState) {
          console.log("Invalid license");
          // Do something for error handling
        }
        console.log("DRM System ID: " + result.drmSystemId);
        console.log("License Server URL: " + result.rightIssueUrl);
      }
    },
    onFailure: function (result) {
        console.log("[" + result.errorCode + "] " + result.errorText);
    }
  });
  //Register subscription handler
  subscriptionHandler = request;
}

// Play video with DRM protection
function playVideo(url) {
    let video = document.getElementById('video');
    let source = document.createElement('source');

    source.setAttribute('src', url);

    if (mediaOption) {
      option = `;mediaOption=${mediaOption}`;
    }
    source.setAttribute('type', mimeType + option);
    video.appendChild(source);

    video.play()
        .then(() => {
            console.log('Video is playing');
        })
        .catch((error) => {
            console.error('Error playing video:', error);
        });

    // Error handling for video element
    video.addEventListener('error', function(event) {
        console.error('Error loading video:', event);
    });

    video.addEventListener('play', function() {
        console.log('Video started playing');
    });

    video.addEventListener('pause', function() {
        console.log('Video paused');
    });

    video.addEventListener('ended', function() {
        console.log('Video ended');
    });
}

// Load DRM client and acquire license when the page is loaded
document.addEventListener('DOMContentLoaded', function() {
  loadDrmClient()
});

index.html

<!DOCTYPE html>
<html>

<head>
	<title>new app</title>
	<style type="text/css">
		body {
			width: 100%;
			height: 100%;
			background-color: #202020;
		}

		div {
			position: absolute;
			height: 100%;
			width: 100%;
			display: table;
		}

		h1 {
			display: table-cell;
			vertical-align: middle;
			text-align: center;
			color: #FFFFFF;
		}

	</style>
</head>

<script src="webOSTVjs-1.2.4/webOSTV.js" charset="utf-8"></script>
<script src="webOSTVjs-1.2.4/webOSTV-dev.js" charset="utf-8"></script>
<script src="index.js"></script>
<script type="text/javascript">
	//sample code for calling LS2 API
	webOS.service.request("luna://com.palm.systemservice", {
		method: "clock/getTime",
		parameters: {},
		onSuccess: function (args) {
			console.log("UTC:", args.utc);
		},
		onFailure: function (args) {
			console.log("Failed to getTime");
		}
	});
</script>

<body>
    <video id="video" controls width="640" height="360"></video>
</body>

</html>

In the webOS TV app, only some specific streaming protocol and DRM combinations are supported. To use PlayReady, you should implement your own player with HTML5 MSE/EME or use third party solutions like Shaka Player. Thank you.