videojs / videojs-contrib-eme

Supports Encrypted Media Extensions for playback of encrypted content in Video.js
Other
203 stars 72 forks source link

Failed to set license with DASH PlayReady #75

Open Dardaxe opened 5 years ago

Dardaxe commented 5 years ago

Hi, I'm trying to play a Dash encoded video with PlayReady DRM and I have some problems with it. As my DRM provider needs a custom header to be passed in the header of the license request I've made this code for the request :

getLicense

"com.microsoft.playready": {
   getLicense: function (emeOptions, keyMessage, callback) {
      const { headers, message } = getMessageContents(keyMessage)
      videojs.xhr({
         url: _DRM_PROVIDER_LICENSE_SERVER_URL_,
         method: 'POST',
         headers: headers,
         body: message,
         responseType: 'arraybuffer'
      }, callback)
   }
}

getMessageContents

const getMessageContents = (message) => {
   const xml = (new window.DOMParser()).parseFromString(
      String.fromCharCode.apply(null, new Uint16Array(message)),
      'application/xml');
   const headersElement = xml.getElementsByTagName('HttpHeaders')[0];
   const headers = {_MY_CUSTOM_HEADER_: _MY_HEADER_DATA_};

   if (headersElement) {
      const headerNames = headersElement.getElementsByTagName('name');
      const headerValues = headersElement.getElementsByTagName('value');

      for (let i = 0; i < headerNames.length; i++) {
         headers[headerNames[i].childNodes[0].nodeValue] =
            headerValues[i].childNodes[0].nodeValue;
      }
   }

   const challengeElement = xml.getElementsByTagName('Challenge')[0];
   let challenge;

   if (challengeElement) {
      challenge = window.atob(challengeElement.childNodes[0].nodeValue);
   }

   return {
      headers,
      message: challenge
   }
}

I'm able to correctly get the license. I can see the license being delivered through my DRM Provider Dashboard and through the network tab in my browser. image

image

However i'm still having this error in my console : image

Here's a link to a test page (Dash PlayReady only compatible with IE/Edge)

Have I missed something in my implementation ? Thanks

misteroneill commented 5 years ago

Unfortunately, we have seen the same issue. We will be (hopefully) working on a fix in the near term for this vendor as it works out of the box when using Dash.js.

misteroneill commented 5 years ago

@Dardaxe Took another look at this issue as we were dealing with the same error message. Our implementation for our PlayReady DRM provider (built on top of contrib-eme) looks like this (cleaned up so as not to leak private stuff):

getLicense(emeOptions, keyMessage, callback) {
  // This is very much the same as your getMessageContents function.
  const parsed = parseKeyMessage(keyMessage);

  videojs.xhr({
    uri: URL_TO_PROVIDER,
    method: 'POST',
    body: parsed.body,
    headers: parsed.headers,
    responseType: 'arraybuffer'
  }, (err, response, body) => {
    if (err) {
      callback(err);
      return;
    }

    callback(null, body);
  });
}

Switching how callback is used may be all you need.

Dardaxe commented 5 years ago

@misteroneill Thanks for your answer and those information !

I've updated videojs-contrib-eme to version 3.5.4 and changed how callback is used. It looks like this now :

getLicense: function (emeOptions, keyMessage, callback) {
   console.log('Playready GetLicense')

   const {headers, message} = getMessageContents(keyMessage)

   videojs.xhr({
      url: 'DRM_PROVIDER_URL',
      method: 'POST',
      body: message,
      headers: headers,
      responseType: 'arraybuffer'
   }, (err, response, responseBody) => {
      if (err) {
         callback(err)
         return
      }
   console.log('License correctly recovered')
   callback(null, responseBody)
   })
}

Unfortunately I'm still getting the same problem: It seems that I'm correctly retrieving the license but it's never set on the player


Calls to my DRM Provider are successfull : image

Console log show the same information : image

I can see them being delivered in my DRM Provider Back office, no problem with that.


Do you think that I need to manually call a specific function to set license on the player ?

Dardaxe commented 5 years ago

I've made a reduced test case, illustrating my problem : https://jsbin.com/wutalosima/edit?html,console,output

Furthermore, it seems like the first request to the DRM Provider have the custom headers I need but the retried requests don't.