10

I've trying to find out how to determine which DRM system browser is using. And in fact, only chrome say it is use 'com.widevine.alpha' where IE & Safari (Win) throw error on 'requestMediaKeySystemAccess', and firefox do not even try to say it use 'com.adobe.acccess' =]

 function isKeySystemSupported(keySystem) {

    var dfd = Q.defer();
    console.log('check: ', keySystem);
    navigator.requestMediaKeySystemAccess(keySystem, [{contentType: 'video/webm; codecs="vp9"'}]).then(function() {
        dfd.resolve(true);
    }, function() { dfd.resolve(false); } );

    return dfd.promise;
}

is there any solution, like Modernizr or similar to get which keySystem I should use?

nilphilus
  • 590
  • 1
  • 5
  • 23
  • check this article which i wrote recently : http://aameer.github.io/articles/digital-rights-management-multi-drm/ it explains in details about how to achieve multi-drm , check the section about about current status – Aameer Nov 16 '17 at 14:50

3 Answers3

14

There are several websites offering such a check, like dash-player.com/browser-capabilities/ After having a closer look at how it is done, one can use something similar to:

// EME Check
var keySystems = {
  widevine: ['com.widevine.alpha'],
  playready: ['com.microsoft.playready', 'com.youtube.playready'],
  clearkey: ['webkit-org.w3.clearkey', 'org.w3.clearkey'],
  primetime: ['com.adobe.primetime', 'com.adobe.access'],
  fairplay: ['com.apple.fairplay']
};
var keySystemsCount = (function () {
  var count = 0;
  for (keysys in keySystems) {
    if (keySystems.hasOwnProperty(keysys)) {
      count += keySystems[keysys].length;
    }
  }
  return count;
})();

var testVideoElement = document.createElement('video');
var supportedSystems = [];
var unsupportedSystems = [];

var supportsEncryptedMediaExtension = function () {
  if (!testVideoElement.mediaKeys) {
    if (window.navigator.requestMediaKeySystemAccess) {
      if (typeof window.navigator.requestMediaKeySystemAccess === 'function') {
        console.log('found default EME');
        hasEME = true;
        var isKeySystemSupported = function (keySystem) {
          var config = [{initDataTypes: ['cenc']}];
          if (window.navigator.requestMediaKeySystemAccess) {
            window.navigator.requestMediaKeySystemAccess(keySystem, config).then(function (keySystemAccess) {
              supportedSystems.push(keySystem);
            }).catch(function () {
              unsupportedSystems.push(keySystem);
            });
          }
        };
        var keysys, dummy, i;
        for (keysys in keySystems) {
          if (keySystems.hasOwnProperty(keysys)) {
            for (dummy in keySystems[keysys]) {
              isKeySystemSupported(keySystems[keysys][dummy]);
            }
          }
        }
      }
    } else if (window.MSMediaKeys) {
      if (typeof window.MSMediaKeys === 'function') {
        console.log('found MS-EME');
        hasEME = true;
        var keysys, dummy, i;
        for (keysys in keySystems) {
          if (keySystems.hasOwnProperty(keysys)) {
            for (dummy in keySystems[keysys]) {
              if (MSMediaKeys.isTypeSupported(keySystems[keysys][dummy])) {
                supportedSystems.push(keySystems[keysys][dummy]);
              } else {
                unsupportedSystems.push(keySystems[keysys][dummy]);
              }
            }
          }
        }
      }
    } else if (testVideoElement.webkitGenerateKeyRequest) {
      if (typeof testVideoElement.webkitGenerateKeyRequest === 'function') {
        console.log('found WebKit EME');
        hasEME = true;
        var keysys, dummy, i;
        for (keysys in keySystems) {
          if (keySystems.hasOwnProperty(keysys)) {
            for (dummy in keySystems[keysys]) {
              if (testVideoElement.canPlayType('video/mp4', keySystems[keysys][dummy])) {
                supportedSystems.push(keySystems[keysys][dummy]);
              } else {
                unsupportedSystems.push(keySystems[keysys][dummy]);
              }
            }
          }
        }
      }
    } else {
      console.log('no supported EME implementation found');
      hasEME = false;
    }
  }
}

Simply run supportsEncryptedMediaExtension() and supportedSystems will be filled with the desired information.

Note that the config object should be extended to include the specific codec claims respective to your particular media. It isn't enough to just detect the key system as codec support sometimes depends on Guest OS dependencies.

var config = [{
     "initDataTypes": ["cenc"],
     "audioCapabilities": [{
          "contentType": "audio/mp4;codecs=\"mp4a.40.2\""
     }],
     "videoCapabilities": [{
          "contentType": "video/mp4;codecs=\"avc1.42E01E\""
     }]
}];
deepelement
  • 2,457
  • 1
  • 25
  • 25
Alexander Wolf
  • 586
  • 3
  • 5
  • 1
    This is great! Where did you find the list of key system strings? I know `org.w3.clearkey` comes from the w3 spec - https://w3c.github.io/encrypted-media/#common-key-systems -. But I have trouble tracking down where the others come from. – Boushley Aug 25 '16 at 12:51
  • 2
    Safari seems to return undefined on the `webkitGenerateKeyRequest` property. Does anyone are experimenting this problem? Thanks – Thiago Miranda de Oliveira Jul 01 '17 at 05:00
5

In addition to the information listed here, I want to mention that in Chrome, whether you are using https or not will affect the availability of navigator.requestMediaKeySystemAccess function.

In your development environment that probably is running on http, navigator.requestMediaKeySystemAccess will return undefined for Chrome whereas the same code will return a function in Firefox.

In your prod environment that has https, navigator.requestMediaKeySystemAccess will return a function both in Chrome and Firefox.

Jason Kim
  • 18,102
  • 13
  • 66
  • 105
5

I had to give videoCapabilities flags to make this work.

function testEME() {
  // https://shaka-player-demo.appspot.com/support.html
  var keySysConfig = [{
    "initDataTypes": ["cenc"]
      //,"persistentState": "required"  // don't use or MacSafari "not supported"
      //,"persistentState": "required", "distinctiveIdentifier": "required"
      //,"audioCapabilities": [{
      //  "contentType": "audio/mp4;codecs=\"mp4a.40.2\""
      //}]
      ,"videoCapabilities": [{
    "contentType": "video/mp4;codecs=\"avc1.4D401E\"" // avc1.42E01E = ConstrainedLevel3, 4D401E=MainLevel3
    //,"robustness": "3000"
      }]
  }];           
        
  var keySystems = {
    playready: ['com.microsoft.playready.recommendation', 'com.microsoft.playready'
      , 'com.microsoft.playready.hardware', 'com.youtube.playready'],
    clearkey: ['webkit-org.w3.clearkey', 'org.w3.clearkey'],
    widevine: ['com.widevine.alpha'],
    primetime: ['com.adobe.primetime', 'com.adobe.access'],
    fairplay: ['com.apple.fairplay','com.apple.fps'
      , 'com.apple.fps.1_0', 'com.apple.fps.2_0', 'com.apple.fps.3_0']
  };
            
  for(keyArr in keySystems) {
    for(forItemIdx in keySystems[keyArr]) {
      let keySys = keySystems[keyArr][forItemIdx];
      try {
         navigator.requestMediaKeySystemAccess(keySys, keySysConfig).
         then(function(mediaKeySystemAccess) {
         //let mkConfig = mediaKeySystemAccess.getConfiguration();
         //let sFlags = "persistentState="+mkConfig.persistentState 
         //  + ", distinctiveIdentifier="+mkConfig.distinctiveIdentifier; 
        console.log(keySys + " supported"); //+" ("+sFlags+")");
      }).catch(function(ex) {
         console.log(keySys+" not supported (" + ex.name+" "+ex.message+")." );
      });
      } catch (ex) {
        console.log(keySys+" not supported (" + ex.name+" "+ex.message+").." );
      }
    }
  }
}
Whome
  • 10,181
  • 6
  • 53
  • 65