📜 ⬆️ ⬇️

Hosting Encrypted Video Content Using HTML5

Not so long ago, a new initiative from W3C - Encrypted Media Extensions or just EME was discussed at Habré. Let's try to figure out in practice what is being offered what is new and interesting.

So, the task: suppose that there is a lot of interesting video that you want to put on the Internet, but not for everyone, but only for good people (for friends, acquaintances, ... or just for money). So, the Encrypted Media Extensions initiative proposes to add all the necessary API for the client part to the HTML standard. In addition, the proposal from W3C addresses other issues, such as the ill-fated DRM, but we will postpone them for now, focusing solely on the client part of the organization of our hypothetical service. A prerequisite is browser support for the EME specification, which means that the underlying key system Clear Key is supported.

So, there is a video tag and a foo.webm file, in which video and audio is encrypted using the AES algorithm (this feature is supported in the WebM container , and the EME authors used this):

 <video src="foo.webm" autoplay></video> 

')
In this situation, the EME browser, when attempting to play foo.webm detects that the content is encrypted, stops, and waits for it to be presented with a key for decryption. In general, the main use case (use case) is that the information about how the content is encrypted is described directly in the container; let's use this option. In addition, the browser will stop, it will also trigger the needkey event on the HTMLMediaElement element itself, and the application should handle it and, ultimately, provide the key:

 <video src="foo.webm" autoplay onneedkey="handleKeyNeeded(event)"></video> 


The handleKeyNeeded() function will not be very complicated - it gets the key identifier that the browser needs, then makes an XHR request to the server and gives the answer = key to the browser back (or does not, if the situation requires it - this is business logic). We will simplify a little - let us have the key already; for the Clear Key + AES scheme that we use, it will be a 16 byte Uint8Array ; then the function looks like this:

 function handleKeyNeeded(event) { var video = event.target; var initData = event.initData; //var message = initData; //var xmlhttp = new XMLHttpRequest(); //xmlhttp.open("POST", "http://.../getkey", false); //xmlhttp.send(message); //var key = new Uint8Array(xmlhttp.response); var key = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); if (!video.keys) video.keys = video.MediaKeys("org.w3.clearkey"); if (!video.keys) throw "Could not create MediaKeys"; var keySession = video.keys.createSession(mimeType, initData); if (!keySession) throw "Could not create key session"; keySession.update(key); } 


The main actors here are:



Those who are interested in the rest of the handleKeyNeeded () function code (MediaKeys, MediaKeySession classes, etc.) can use a fresh translation of the future EME specification, made using the Catbo service.

Thus, if we had a browser with EME support (current version 2), then on the encrypted_media_player_v2.html page, we would find on the video a black bear walking around the cage (a sample of the encrypted video bear-320x240-av-enc_av.webm taken from Chromium code). At the time of this writing, there is probably no such browser. However, if you slightly modify the page code, you can still see the bear using Google Chrome or Chromium browsers version 26 or higher (while support is only found in them): encrypted_media_player.html .

Next, we consider what improvements had to be done to make our example work. First, Chrome / Chromium currently supports version 1 of the future EME specification, which EME authors have already abandoned in favor of version 2, making the latter object-oriented. However, only the first version of EME is enabled in Chrome / Chromium; in addition, in many places you need to hang the webkit prefix; handleKeyNeeded() this, the handleKeyNeeded() function will change as follows:

 function handleKeyNeeded(event) { ... var keySystem = "webkit-org.w3.clearkey"; video.webkitGenerateKeyRequest(keySystem, event.initData); //   video.webkitAddKey(keySystem, key, event.initData, null); } 


Secondly, if we now directly set the src attribute of the video tag, we will not wait for the needkey events. The fact is that in this case, the video is played by the stock functionality of ffmpeg, which is involved in the browser, and he does not pay attention to any encryption flags in the container (there are few technical details on the implementation of the media stack in Chrome / Chrome). But if we use a different way of providing content to the player, then we will get the result we need (exciting the needkey event). This other method is called Media Source Extensions ; its essence lies in the fact that the JavaScript code is allowed to generate a media stream for later playback. In practice, this means that an alternative implementation of demuxers , such as WebM and mp4, has appeared in Google’s browsers; that's what taught them to the excitation of the needkey event that we need. Here is the corresponding code for uploading a video with a bear to our video tag:

 function load() { var video = document.getElementById("video"); var mediaFile = "bear-320x240-av-enc_av.webm"; //video.src = mediaFile; var sourceOpened = false; function onSourceOpen(e) { if (sourceOpened) return; sourceOpened = true; var mediaType = 'video/webm; codecs="vorbis, vp8"'; var srcBuffer = mediaSource.addSourceBuffer(mediaType); var xhr = new XMLHttpRequest(); xhr.open('GET', mediaFile); xhr.responseType = 'arraybuffer'; xhr.addEventListener('load', function(e) { srcBuffer.append(new Uint8Array(e.target.response)); mediaSource.endOfStream(); }); xhr.send(); } var mediaSource = new WebKitMediaSource(); mediaSource.addEventListener('webkitsourceopen', onSourceOpen); video.src = window.URL.createObjectURL(mediaSource); ... } 


Of course, this code is less universal than simple assignment.

 video.src = "bear-320x240-av-enc_av.webm"; 


; Moreover, the future EME specification does not require such tweaks (but for the time being it is only possible to achieve efficiency in this way). We look forward to further developments.




Outside this article, there is the question of how to encrypt video. This task is container-specific; for example, WebM has this capability, but this is not true for some other containers, etc.

Links to EME:
Google, Microsoft and Netflix want to add DRM to HTML5
Translation of Encrypted Media Extensions specification / Encrypted HTML5 media content

Source: https://habr.com/ru/post/176115/


All Articles