How to Play MPEG-DASH Encrypted Protected Content Using Encrypted Media Extensions (EME) in Browser

in mpeg-dash •  2 years ago 

Long title right? Let's break it and go step by step.

How do you play a normal mp4 media in browser?

All you need to do in an HTML document is to add the video URL to the element by using the <source> element.

Let's see a simple example.

image.png

pretty simple right? Let's see how you can play MPEG-DASH.

Ah, wait, MPEG-DASH?

What is MPEG-DASH?

image.png

Adaptive bitrate streaming over HTTPMPEG DASH (Dynamic Adaptive Streaming over HTTP) is a streaming standard by MPEG that enables streaming of media content over the Internet delivered from conventional HTTP web servers.
It provides interoperability between various servers and devices i.e this is one such common video streaming which supports all the formats and plays in various devices.

How does it work?

It works by breaking the content into a sequence of small segments, which are served over HTTP.

In our example, we could split the .mp4 file into small playable chunk of content (for audio, video or captions) with a length of usually few seconds. This is what 'streaming' is where the chunks are served constantly so that a device can start displaying the data without having to download the entire video file before playing it.

we could also have alternative segments encoded at different bit rates. Client monitors the network bandwidth and decides how to adapt to the available bandwidth by fetching segments of different alternatives. This is what makes it 'adaptive' and hence 'dynamic'.

You could read more about MPEG-DASH here: https://bitmovin.com/dynamic-adaptive-streaming-http-mpeg-dash/

Let's see how we can generate a DASH content :

We have a regular .mp4 file, we will use Bento4 tools for generating DASH content from it.

The first thing we will need to do is creating a fragmented version of our regular mp4 file. (more about mp4fragment here: https://www.bento4.com/documentation/mp4fragment/)

mp4fragment video.mp4 video-fragmented.mp4

Now, packaging it as a MPEG-DASH stream (more about mp4dash here : https://www.bento4.com/documentation/mp4dash/)

mp4dash -o output video-fragmented.mp4

You would now see a 'output' folder structure something like this :

audio
|---segments folder
video
|---segments folder
stream.mpd

you could see there is .mpd file generated. MPD (Media Presentation Description) describes a manifest of the available content, its various alternatives, their URL addresses, and other characteristics.
To play the content, you need to tell player where to find individual segments - that is the purpose of manifest and that's what the browser needs.

How to play MPEG-DASH ?

Now you would think, you could give URL of the mpd file in the video tag and you are good to go. NO, that's not it.
Browsers do not have native support for MPEG-DASH. You would need JavaScript libraries to play DASH streaming. There are open source MPEG-DASH player libraries available for it.

  1. dash.js: Official reference client implementation
  2. Shaka Player: Google's player library

There might also be some other libraries to implement DASH playback in browsers. Most of these player libraries require MSE support in the browser which I think is the case anyways in many latest browsers today.

We are going to be using dash.js library here to play the MPEG-DASH video in the browser.
With that, I think it would be good to have a look at https://docs.microsoft.com/en-us/azure/media-services/previous/media-services-embed-mpeg-dash-in-html5 which has explained step by step process on how to do it.

If you read through the above link, you would know that you just need to add 'dash.all.js' file in your .html file and a function which attaches video element to Dash player.

Now the html file would look something like this :

image.png

Point your browser at this .html file and click play , you are done!

NOTE : Make sure you are not just pointing your browser at this .html in your local folder, but start a web server to host your directory that has this .html file, because, DASH is to be delivered over HTTP.
You can go to the directory from your command prompt and run :

python -m SimpleHTTPServer (python2)
or
python3 -m http.server (python3) 

which usually hosts directory listing at http://localhost:8000
We are now done with 'How to play MPEG-DASH' from the title, let's get into Encryption and EME.

Encryption and EME :

image.png

Let's first try to understand what EME is and how it works!
There are other better resources which would explain about EME in better way.
https://developers.google.com/web/fundamentals/media/eme
or the EME specification itself : https://www.w3.org/TR/encrypted-media/
I would anyways try to put it in a simpler way.

what is EME and how it works?

You have this Content Decryption Module (CDM): A client component native to browser that decrypts the media.
But, CDM needs the license/key to decrypt and it does not directly make any network request to the remote license server which holds the content keys but the request for the license is communicated by the JavaScript application, which uses the EME API to make the network requests.

To the JS application using EME, the messages communicated between CDM and license server are opaque, and any tampering of the messages can be easily detected by the DRM system.

So, the Information flow would be,

  1. The application has to figure out what key system to use when it finds that the content is encrypted(navigator.requestMediaKeySystemAccess() to find the available Key System). Key System refers to the specific Content Decryption Module schema

  2. Initialise the keys : Create MediaKeys object and associate it with HTMLMediaElement

  3. Create a session during which the keys are valid (createMediaKeySession object on the MediaKeys object).

  4. A request is sent to the CDM to generate the license request (call the generateRequest() method on the MediaKeySession object, with the initialisation data sent in the metadata of the encrypted media file.

  5. The CDM sends license request to the application.

  6. The application send this request to the license server and gets the license.

  7. Application forwards the license to the CDM with the update method on the MediaKeySession object and then the media is played.

Demo with clear-key keySystem

Now you understand that EME API does not define any CDM, it does not define key server, it just mediates information flow between those.

Having said that, how can I test the EME APIs in my browser if I do not have license/key server or a decryption module?

Well, Although EME does not define DRM functionality, the spec currently mandates that all browsers supporting EME must implement Clear Key (https://www.w3.org/TR/encrypted-media/#common-key-systems).

Using this system, media can be encrypted with a key and then played back simply by providing that key. Clear Key can be built into the browser: it does not require the use of a separate decryption module.
EME spec also defines the format of license request and license response for Clear key. So, we could write code to check the EME API works the way we mentioned earlier.

This is not the case with other key systems , eg: Google's widevine for which we need to have the widevine license/key server and Widevine CDM.

Encrypting the media with Clear key :

There is already a page from Dash-Industry-Forum explaining it.

You could have a look at https://github.com/Dash-Industry-Forum/dash.js/wiki/Generate-MPEG-DASH-content-encrypted-with-MPEG-CENC-ClearKey to see how it's done.

Playing the Clear key encrypted media :

We already know that media is Clear Key encrypted, so we can get access to Key system and initialise the keys (i.e the first 2 steps mentioned in the Information flow earlier)

image.png

Now, when the media element raises an 'encrypted' event, application can handle the event with below code (handleEncrypted() function) to update the session with license so that the media can be decrypted (Steps from 3 to 7 mentioned in the Information flow earlier)

image.png

Adding everything up, you could look at https://htmlpreview.github.io/?https://github.com/sanjuc/clear-key/blob/master/index.html for demo of playback of Clear Key encrypted media. You could look at the console warn messages to see the sequence of events in the process.
Also, the source code is at https://github.com/sanjuc/clear-key.

Thanks for reading :)

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!