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>
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>
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 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); }
event.initData
: an identifier, the corresponding key is needed by the browser;key
: the actual key to decrypt;keySession.update(key)
: with this call, the browser gets the same key; more from the page and is not required.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 .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); }
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); ... }
video.src = "bear-320x240-av-enc_av.webm";
Source: https://habr.com/ru/post/176115/
All Articles