Client Player Applications

A crucial component of the MSE-EME experience is a Javascript application running on the browser that performs the following tasks:

  • Parsing the DASH manifest (.mpd)
  • Retrieving DASH media files according to detected bandwidth availability
  • Calling MSE APIs to pass media segments into the browser's media engine
  • Calling EME APIs to retrieve licenses and store them in the CDM for decrypting of protected media

dash.js Player

CableLabs has played an integral role in adding support for protected content in the open-source dash.js reference implementation from the DASH Industry Forum. Here are a list of features that you can find in the player:

  • EME Abstraction API: Due to the fact that the EME specification is just now gaining some stability, browser vendors have had to select different points in the lifetime of the spec at which to provide their implementation. dash.js provides an EME abstraction API (which attempts to mimic the latest version of EME) that provides a consistent interface for app developers while still enabling protected content playback on a variety of user agents.
  • Multi-DRM Support: dash.js supports playback of Microsoft PlayReady, Google Widevine, and ClearKey. Adobe Access DRM support is planned.
  • Common Encryption and Multi-DRM: dash.js supports the CommonEncryption (cenc) initialization data type. PSSH data can be carried in the media or in the manifest (manifest initData takes priority). App developers can override the default selection policy of dash.js to determine how a DRM is chosen based on media and browser capabilities.
  • Flexible License Server Communications: When developing a production player, your business needs will determine which license servers you contact and how you communicate with them. dash.js contains an extensible mechanism for allowing applications to provide their own protocols (messages, HTTP headers, etc) for interaction with the license server.
  • License Pre-Fetch: When initialization data is present in the DASH manifest, it is possible to "pre-fetch" licenses for content wihtout downloading media segments dash.js allows applications to parse manifests and perform EME operations outside the media player. Pre-fetched licenses can then be attached to the media player when initiating playback to prevent delays in presenting the content.
  • EME Demo Application: A sample application is provided that shows how to use the EME capabilities of the player to prefetch licenses, modify key session persistence and peform persistence operations, and attach license information to the media player for playback. The application displays a graphical representation for each content item showing the DRM system in use, the key sessions, and status for all licenses.


The Fraunhofer FOKUS group has developed their own dashjs-based player application. They claim to have enchanced the application to facilitate faster switching between different bitrates. The application also contains links to some sample encrypted media and a graphical dispay that takes you through the various EME events and processes as they occur during playback.

In addition to the player, Fraunhofer has also integrated a Microsoft PlayReady CDM into a build of the Chromium open source browser from Google.

Please contact Fraunhofer directly for more information on their MSE/EME browser and player application.

Microsoft TestDrive Site

Microsoft has written an EME test application as part of their Test Drive site. The HTML5 EME Test Drive application contains both clear and unencrypted adaptive bitrate media that you can use to validate Microsoft PlayReady support on a given browser platform.


The table below details the various aspects of each browser we have tested as they pertain to support for MSE/EME and playback of encrypted content.

Browser CDMs MSE EME
IE Icon Internet Explorer 11 PlayReady Yes Yes
- MediaKeyNeededEvent attributes (unstable in the spec)
Chrome Icon Chrome (Milestone 42) Widevine, ClearKey Yes Yes
FAMIUM (Chromium, Milestone 30) PlayReady Yes Partial
- MediaKeys.isTypeSupported() missing
- MediaKeyNeededEvent attributes (unstable in the spec)

License Servers


The castLabs DRMToday multi-DRM licensing service provides content encryption and packaging capabilities as well as the license server for protected media. Contact DRMToday to setup an account which will enable you to create content with the CableLabs tools and playback using the dash.js player.

Microsoft PlayReady Test Server

Microsoft provides a test license server that is chock full of features needed for testing your browser and CDM. The documentation page details all of the supported query string arguments for requesting various types of licenses. Also on this page, you can find the license server's key seed value. This is the value used in our PlayReadyKeyGen tool to generate keys and checksums that will work with the test license server. One additional feature of the test server is the ability to specify your own key value (via the ContentKey query string arg). This is a handy feature when you don't want the license server to select a key based on the key generation algorithm. However, keep in mind that this does not emulate real-world security, since the key can be seen clearly in the URL request.

Widevine License Server

Contact Google Widevine to setup your own customer portal on the Widevine license service. The information they provide you will allow you to create content with the CableLabs encryption tools and to playback that content using dash.js

Adobe Test Server

Coming Soon

CableLabs ClearKey Test Server

As we showed in a previous section, we can indicate in our 'pssh' the desire to retrieve our Clear Key decryption keys from a remote URL. We have implemented a very simple server process using Node.js to return hard-coded decryption keys based on query string arguments passed in the URL. The server code itself is extremely simple:

var https = require('https');
var http = require('http');
var fs = require('fs');
var url = require('url');

keys = {
    '10000000100010001000100000000001': new Buffer("3A2A1B68DD2BD9B2EEB25E84C4776668", 'hex'),
    '10000000100010001000100000000002': new Buffer("04714BD8D7E1F3815FC47D0A834F0E18", 'hex')

var options = {
    key: fs.readFileSync('security/cl_clearkey-key.pem'),
    cert: fs.readFileSync('security/cl_clearkey-cert.pem')

var addCORSHeaders = function(res, length) {
    res.writeHeader(200, {
        "Content-Length": length,
        "Content-Type": 'application/json',
        "Access-Control-Allow-Origin": '*',
        "Access-Control-Allow-Methods": 'GET, PUT, POST, DELETE, OPTIONS',
        "Access-Control-Allow-Headers": 'Content-Type, Authorization, Content-Length, X-Requested-Width'});

// Still testing this
https.createServer(options, function(req, res) {
    res.end("hello world\n");


http.createServer(function(req, res) {
    var parsed_url = url.parse(req.url, true);
    var query = parsed_url.query;

    // Validate query string
    if (query === undefined || query.keyid === undefined) {
        res.writeHeader(400, "Illegal query string");

    var keyIDs = [];
    if (query.keyid instanceof Array) {
        keyIDs = query.keyid;
    } else {

    var jwk_array = [];
    for (var i = 0; i < keyIDs.length; i++) {
        var jwk = {
            kty: "oct",
            alg: "A128GCM",
            kid: new Buffer(keyIDs[i], 'hex').toString('base64').replace(/=/g, ""),
            k: keys[keyIDs[i]].toString('base64').replace(/=/g, "")
    var response = {
        keys: jwk_array
    var json_str_response = JSON.stringify(response);
    addCORSHeaders(res, json_str_response.length);


You can see from the query string arguments that the server supports querying of multiple key Ids in a single request. The JSON Web Key syntax supports multiple keys as well, so the server will return exactly the number of keys you requested (assuming the key IDs have been coded into the server). One other item of note in the server source code is the addition of CORS headers. These allow the client application, which may be served from a different host, to retrieve data from the clear key license server no matter where it resides.