Les API Encrypted Media Extensions fournissent une API qui permet aux applications Web d'interagir avec les systèmes de protection de contenu afin de permettre la lecture de contenus audio et vidéo chiffrés.
EME est conçu pour permettre d'utiliser la même application et les mêmes fichiers chiffrés dans n'importe quel navigateur, quel que soit le système de protection sous-jacent. Le premier est rendu possible par les API et le flux standardisés, tandis que le second l'est par le concept de chiffrement commun.
EME est une extension de la spécification HTMLMediaElement, d'où son nom. Étant donné qu'il s'agit d'une "extension", la compatibilité du navigateur avec EME est facultative: si un navigateur n'est pas compatible avec les contenus multimédias chiffrés, il ne pourra pas les lire, mais EME n'est pas obligatoire pour la conformité aux spécifications HTML. D'après la spécification EME:
Cette proposition étend HTMLMediaElement en fournissant des API permettant de contrôler la lecture de contenu protégé.
L'API prend en charge des cas d'utilisation allant du déchiffrement de clé claire simple à la vidéo haute fidélité (avec une implémentation d'agent utilisateur appropriée). L'échange de licence/clé est contrôlé par l'application, ce qui facilite le développement d'applications de lecture robustes compatibles avec une gamme de technologies de déchiffrement et de protection du contenu.
Cette spécification ne définit pas de système de protection du contenu ni de gestion des droits numériques. Il définit plutôt une API commune qui peut être utilisée pour découvrir, sélectionner et interagir avec ces systèmes, ainsi qu'avec des systèmes de chiffrement de contenu plus simples. L'implémentation de la gestion des droits numériques n'est pas requise pour la conformité à cette spécification : seul le système Clear Key doit être implémenté comme référence commune.
L'API commune prend en charge un ensemble simple de fonctionnalités de chiffrement de contenu, laissant les fonctions d'application telles que l'authentification et l'autorisation aux auteurs de pages. Pour ce faire, la page doit assurer la médiation des messages spécifiques au système de protection du contenu plutôt que de supposer une communication hors bande entre le système de chiffrement et une licence ou un autre serveur.
Les implémentations EME utilisent les composants externes suivants :
- Système de clés : mécanisme de protection du contenu (DRM). La gestion EME ne définit pas les systèmes de clés eux-mêmes, à l'exception de la clé d'effacement (plus d'informations à ce sujet ci-dessous).
- Module de déchiffrement de contenu (CDM, Content Decryption Module) : mécanisme logiciel ou matériel côté client qui permet la lecture de contenus multimédias chiffrés. Comme pour les systèmes de clés, EME ne définit aucun CDM, mais fournit une interface permettant aux applications d'interagir avec les CDM disponibles.
- Serveur de licences (clés):interagit avec un CDM pour fournir des clés permettant de déchiffrer des contenus multimédias. La négociation avec le serveur de licences relève de la responsabilité de l'application.
- Service de packaging : encode et chiffre les contenus multimédias pour la distribution/consommation.
Notez qu'une application utilisant l'EEM interagit avec un serveur de licences pour obtenir des clés permettant le déchiffrement, mais que l'identité et l'authentification de l'utilisateur ne font pas partie de la EME. La récupération des clés pour permettre la lecture multimédia se produit après l'authentification (facultatif) d'un utilisateur. Des services tels que Netflix doivent authentifier les utilisateurs dans leur application Web: lorsqu'un utilisateur se connecte à l'application, celle-ci détermine son identité et ses privilèges.
Comment fonctionne la EME ?
Voici comment les composants de l'EME interagissent, ce qui correspond à l'exemple de code ci-dessous :
Si plusieurs formats ou codecs sont disponibles, vous pouvez utiliser MediaSource.isTypeSupported() ou HTMLMediaElement.canPlayType() pour sélectionner le bon. Toutefois, le CDM peut ne prendre en charge qu'une partie de ce que le navigateur accepte pour le contenu non chiffré. Il est préférable de négocier une configuration MediaKeys avant de sélectionner un format et un codec. Si l'application attend l'événement chiffré, mais que MediaKeys indique qu'il ne peut pas gérer le format/codec choisi, il sera peut-être trop tard pour changer de format sans interrompre la lecture.
Le flux recommandé consiste à négocier d'abord MediaKeys, à l'aide de MediaKeysSystemAccess.getConfiguration() pour connaître la configuration négociée.
S'il n'y a qu'un seul format/codec à choisir, getConfiguration() n'est pas nécessaire. Toutefois, il est toujours préférable de configurer MediaKeys en premier. La seule raison d'attendre l'événement chiffré est s'il n'y a aucun moyen de savoir si le contenu est chiffré ou non, mais en pratique, ce n'est pas probable.
- Une application Web tente de lire de l'audio ou de la vidéo avec un ou plusieurs flux chiffrés.
- Le navigateur reconnaît que le contenu multimédia est chiffré (voir encadré ci-dessous pour savoir comment cela se produit) et déclenche un événement chiffré avec des métadonnées (initData) obtenues à partir du contenu multimédia sur le chiffrement.
L'application gère l'événement chiffré:
Si aucun objet MediaKeys n'a été associé à l'élément multimédia, sélectionnez d'abord un système de clés disponible à l'aide de navigator.requestMediaKeySystemAccess() pour vérifier quels systèmes de clés sont disponibles, puis créez un objet MediaKeys pour un système de clés disponible via un objet MediaKeySystemAccess. Notez que l'initialisation de l'objet MediaKeys doit avoir lieu avant le premier événement chiffré. L'application obtient une URL de serveur de licences indépendamment de la sélection d'un système de clés disponible. Un objet MediaKeys représente toutes les clés disponibles pour déchiffrer le contenu multimédia d'un élément audio ou vidéo. Il représente une instance CDM et permet d'y accéder, en particulier pour créer des sessions de clés, qui sont utilisées pour obtenir des clés auprès d'un serveur de licences.
Une fois l'objet MediaKeys créé, attribuez-le à l'élément multimédia: setMediaKeys() associe l'objet MediaKeys à un HTMLMediaElement, afin que ses clés puissent être utilisées pendant la lecture, c'est-à-dire pendant le décodage.
L'application crée une MediaKeySession en appelant createSession() sur les MediaKeys. Cela crée une MediaKeySession, qui représente la durée de vie d'une licence et de ses clés.
L'application génère une demande de licence en transmettant les données multimédias obtenues dans le gestionnaire chiffré au CDM, en appelant generateRequest() sur la MediaKeySession.
Le CDM déclenche un événement de message: une requête visant à acquérir une clé auprès d'un serveur de licence.
L'objet MediaKeySession reçoit l'événement de message et l'application envoie un message au serveur de licence (via XHR, par exemple).
L'application reçoit une réponse du serveur de licences et transmet les données au CDM à l'aide de la méthode update() de MediaKeySession.
Le CDM déchiffre les contenus multimédias à l'aide des clés de la licence. Une clé valide peut être utilisée, à partir de n'importe quelle session dans les MediaKeys associées à l'élément multimédia. Le CDM accédera à la clé et à la stratégie, indexées par ID de clé.
La lecture des contenus multimédias reprend.
Comment le navigateur sait-il que le contenu multimédia est chiffré ?
Ces informations se trouvent dans les métadonnées du fichier de conteneur multimédia, qui sera au format ISO BMFF ou WebM, par exemple. Pour ISO BMFF, il s'agit des métadonnées d'en-tête, appelées zone d'information du schéma de protection. WebM utilise l'élément Matroska ContentEncryption, avec quelques ajouts spécifiques à WebM. Des consignes sont fournies pour chaque conteneur dans un registre spécifique à l'EME.
Notez qu'il peut y avoir plusieurs messages entre le CDM et le serveur de licences, et que toutes les communications de ce processus sont opaques pour le navigateur et l'application : les messages ne sont compris que par le CDM et le serveur de licences, bien que la couche d'application puisse voir le type de message que le CDM envoie. La demande de licence contient une preuve de la validité (et de la relation de confiance) du CDM, ainsi qu'une clé à utiliser lors du chiffrement de la ou des clés de contenu dans la licence générée.
Mais à quoi servent-elles ?
Une implémentation EME ne permet pas en soi de déchiffrer les contenus multimédias : elle fournit simplement une API permettant à une application Web d'interagir avec les modules de déchiffrement de contenu.
La spécification EME ne définit pas ce que font réellement les CDM. Un CDM peut gérer le décodage (décompression) des contenus multimédias ainsi que le déchiffrement. Du moins au plus robuste, plusieurs options sont possibles pour la fonctionnalité CDM:
- Déchiffrement uniquement, ce qui permet la lecture à l'aide du pipeline multimédia normal, par exemple via un élément <video>.
- Décryptage et décodage, en transmettant les images vidéo au navigateur pour affichage.
- Le déchiffrement et le décodage, le rendu directement dans le matériel (par exemple, le GPU).
Il existe plusieurs façons de mettre un CDM à la disposition d'une application Web :
- Associez un CDM au navigateur.
- Distribuez un CDM séparément.
- Intégrer un CDM au système d'exploitation
- Incluez un CDM dans le micrologiciel.
- Intégrer un CDM dans le matériel
La manière dont un CDM est mis à disposition n'est pas définie par la spécification EME, mais dans tous les cas, le navigateur est responsable de l'examen et de l'exposition du CDM.
EME n'impose pas de système de clés particulier. Parmi les navigateurs pour ordinateur et mobile actuels, Chrome est compatible avec Widevine et IE11 avec PlayReady.
Obtenir une clé à partir d'un serveur de licences
Dans le cadre d'un usage commercial classique, le contenu est chiffré et encodé à l'aide d'un service ou d'un outil de packaging. Une fois le contenu multimédia chiffré disponible en ligne, un client Web peut obtenir une clé (incluse dans la licence) auprès d'un serveur de licences et l'utiliser pour permettre le déchiffrement et la lecture du contenu.
Le code suivant (adapté des exemples de spécifications) montre comment une application peut sélectionner un système de clés approprié et obtenir une clé auprès d'un serveur de licences.
var video = document.querySelector('video');
var config = [{initDataTypes: ['webm'],
videoCapabilities: [{contentType: 'video/webm; codecs="vp09.00.10.08"'}]}];
if (!video.mediaKeys) {
navigator.requestMediaKeySystemAccess('org.w3.clearkey',
config).then(
function(keySystemAccess) {
var promise = keySystemAccess.createMediaKeys();
promise.catch(
console.error.bind(console, 'Unable to create MediaKeys')
);
promise.then(
function(createdMediaKeys) {
return video.setMediaKeys(createdMediaKeys);
}
).catch(
console.error.bind(console, 'Unable to set MediaKeys')
);
promise.then(
function(createdMediaKeys) {
var initData = new Uint8Array([...]);
var keySession = createdMediaKeys.createSession();
keySession.addEventListener('message', handleMessage,
false);
return keySession.generateRequest('webm', initData);
}
).catch(
console.error.bind(console,
'Unable to create or initialize key session')
);
}
);
}
function handleMessage(event) {
var keySession = event.target;
var license = new Uint8Array([...]);
keySession.update(license).catch(
console.error.bind(console, 'update() failed')
);
}
Chiffrement commun
Les solutions de chiffrement commun permettent aux fournisseurs de contenus de chiffrer et d'empaqueter leur contenu une fois par conteneur/codec, et de l'utiliser avec divers systèmes de clés, CDM et clients, c'est-à-dire tout CDM compatible avec le chiffrement commun. Par exemple, une vidéo empaquetée à l'aide de PlayReady peut être lue dans un navigateur à l'aide d'un CDM Widevine obtenant une clé auprès d'un serveur de licences Widevine.
Contrairement aux anciennes solutions qui ne fonctionnaient qu'avec une pile verticale complète, y compris un seul client qui comprenait souvent également un environnement d'exécution d'application.
Le chiffrement commun (CENC) est une norme ISO qui définit un schéma de protection pour le format ISO BMFF. Un concept similaire s'applique au format WebM.
Effacer la clé
Bien qu'EME ne définisse pas de fonctionnalité DRM, la spécification exige actuellement que tous les navigateurs prenant en charge la EME doivent implémenter une clé d'effacement. Grâce à ce système, les contenus multimédias peuvent être chiffrés à l'aide d'une clé, puis lus simplement en fournissant cette clé. Clear Key peut être intégrée au navigateur: elle ne nécessite pas l'utilisation d'un module de déchiffrement distinct.
Bien qu'il ne soit pas susceptible d'être utilisé pour de nombreux types de contenus commerciaux, Clear Key est entièrement interopérable avec tous les navigateurs compatibles avec EME. Il est également pratique pour tester les implémentations EME et les applications utilisant EME, sans avoir à demander une clé de contenu à un serveur de licence. Vous trouverez un exemple simple de clé transparente sur simpl.info/ck. Vous trouverez ci-dessous une présentation du code, qui correspond aux étapes décrites ci-dessus, mais sans interaction avec le serveur de licences.
// Define a key: hardcoded in this example
// – this corresponds to the key used for encryption
var KEY = new Uint8Array([
0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, 0x68, 0xef, 0x12, 0x2a, 0xfc,
0xe4, 0xae, 0x3c,
]);
var config = [
{
initDataTypes: ['webm'],
videoCapabilities: [
{
contentType: 'video/webm; codecs="vp8"',
},
],
},
];
var video = document.querySelector('video');
video.addEventListener('encrypted', handleEncrypted, false);
navigator
.requestMediaKeySystemAccess('org.w3.clearkey', config)
.then(function (keySystemAccess) {
return keySystemAccess.createMediaKeys();
})
.then(function (createdMediaKeys) {
return video.setMediaKeys(createdMediaKeys);
})
.catch(function (error) {
console.error('Failed to set up MediaKeys', error);
});
function handleEncrypted(event) {
var session = video.mediaKeys.createSession();
session.addEventListener('message', handleMessage, false);
session
.generateRequest(event.initDataType, event.initData)
.catch(function (error) {
console.error('Failed to generate a license request', error);
});
}
function handleMessage(event) {
// If you had a license server, you would make an asynchronous XMLHttpRequest
// with event.message as the body. The response from the server, as a
// Uint8Array, would then be passed to session.update().
// Instead, we will generate the license synchronously on the client, using
// the hard-coded KEY at the top.
var license = generateLicense(event.message);
var session = event.target;
session.update(license).catch(function (error) {
console.error('Failed to update the session', error);
});
}
// Convert Uint8Array into base64 using base64url alphabet, without padding.
function toBase64(u8arr) {
return btoa(String.fromCharCode.apply(null, u8arr))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=*$/, '');
}
// This takes the place of a license server.
// kids is an array of base64-encoded key IDs
// keys is an array of base64-encoded keys
function generateLicense(message) {
// Parse the clearkey license request.
var request = JSON.parse(new TextDecoder().decode(message));
// We only know one key, so there should only be one key ID.
// A real license server could easily serve multiple keys.
console.assert(request.kids.length === 1);
var keyObj = {
kty: 'oct',
alg: 'A128KW',
kid: request.kids[0],
k: toBase64(KEY),
};
return new TextEncoder().encode(
JSON.stringify({
keys: [keyObj],
}),
);
}
Pour tester ce code, vous devez lire une vidéo chiffrée. Vous pouvez chiffrer une vidéo à utiliser avec Clear Key pour WebM en suivant les instructions de webm_crypt. Des services commerciaux sont également disponibles (pour ISO BMFF/MP4 au moins) et d'autres solutions sont en cours de développement.
Technologie associée 1: extensions de source multimédia (MSE)
L'élément HTMLMediaElement est d'une beauté simple.
Nous pouvons charger, décoder et lire des contenus multimédias simplement en fournissant une URL de source :
<video src="foo.webm"></video>
L'API Media Source est une extension de HTMLMediaElement qui permet un contrôle plus précis de la source multimédia, en permettant à JavaScript de créer des flux pour la lecture à partir de "blocs" de vidéo. Cela permet à son tour des techniques telles que le streaming adaptatif et le décalage temporel.
Pourquoi le MSE est-il important pour l'EME ? En effet, en plus de distribuer du contenu protégé, les fournisseurs de contenus commerciaux doivent pouvoir adapter la diffusion de contenu aux conditions du réseau et à d'autres exigences. Netflix, par exemple, modifie de manière dynamique le débit de streaming en fonction des conditions du réseau. EME fonctionne avec la lecture de flux multimédias fournis par une implémentation MSE, comme avec des flux multimédias fournis via un attribut src.
Comment découper et lire des contenus multimédias encodés à différents débits ? Consultez la section DASH ci-dessous.
Vous pouvez voir le MSE en action sur simpl.info/mse. Pour les besoins de cet exemple, une vidéo WebM est divisée en cinq fragments à l'aide des API File. Dans une application de production, des fragments de vidéo sont récupérés via AJAX.
Un SourceBuffer est d'abord créé :
var sourceBuffer = mediaSource.addSourceBuffer(
'video/webm; codecs="vorbis,vp8"',
);
Le film entier est ensuite diffusé en "flux" vers un élément vidéo en ajoutant chaque fragment à l'aide de la méthode "appendBuffer()" :
reader.onload = function (e) {
sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
if (i === NUM_CHUNKS - 1) {
mediaSource.endOfStream();
} else {
if (video.paused) {
// start playing after first chunk is appended
video.play();
}
readChunk_(++i);
}
};
Pour en savoir plus sur le MSE, consultez le guide de présentation du MSE.
Technologie associée 2: streaming adaptatif dynamique sur HTTP (DASH)
Multi-appareil, multiplate-forme, mobile : quel que soit le terme que vous utilisiez, le Web est souvent utilisé dans des conditions de connectivité changeante. La diffusion dynamique et adaptative est essentielle pour faire face aux contraintes de bande passante et à la variabilité dans le monde multi-appareil.
DASH (également appelé MPEG-DASH) est conçu pour offrir la meilleure diffusion multimédia possible dans un monde instable, à la fois pour le streaming et le téléchargement. Plusieurs autres technologies fonctionnent de manière similaire, comme le HTTP Live Streaming (HLS) d'Apple et le Smooth Streaming de Microsoft, mais DASH est la seule méthode de streaming à débit adaptatif via HTTP basée sur une norme ouverte. DASH est déjà utilisé par des sites tels que YouTube.
Quel est le rapport avec EME et MSE ? Les implémentations DASH basées sur MSE peuvent analyser un fichier manifeste, télécharger des segments de vidéo à un débit approprié et les transmettre à un élément vidéo dès qu'il en a besoin, à l'aide d'une infrastructure HTTP existante.
En d'autres termes, DASH permet aux fournisseurs de contenus commerciaux de diffuser du contenu protégé en streaming adaptatif.
DASH réagit à ce qui est indiqué sur l'écran:
- Dynamique:s'adapte aux conditions changeantes.
- Adaptatif:s'adapte pour fournir un débit audio ou vidéo approprié.
- Streaming : permet de regarder des contenus en streaming et de les télécharger.
- HTTP:permet de diffuser du contenu avec les avantages du protocole HTTP, sans les inconvénients d'un serveur de streaming traditionnel.
La BBC a commencé à fournir des flux de test avec DASH :
Le contenu multimédia est encodé plusieurs fois à différents débits. Chaque encodage est appelé "représentation". Ceux-ci sont divisés en plusieurs segments multimédias. Le client joue un programme en demandant des segments, dans l'ordre, à partir d'une représentation via HTTP. Les représentations peuvent être regroupées dans des ensembles d'adaptations de représentations contenant du contenu équivalent. Si le client souhaite modifier le débit, il peut choisir une alternative dans l'ensemble d'adaptation actuel et commencer à demander des segments à partir de cette représentation. Le contenu est encodé de manière à faciliter le passage du client. En plus d'un certain nombre de segments multimédias, une représentation comporte généralement également un segment d'initialisation. On peut considérer qu'il s'agit d'un en-tête contenant des informations sur l'encodage, les tailles de frame, etc. Un client doit l'obtenir pour une représentation donnée avant de consommer des segments multimédias à partir de cette représentation.
En résumé :
- Les contenus multimédias sont encodés à différents débits.
- Les différents fichiers de débit sont mis à disposition à partir d'un serveur HTTP.
- Une application Web cliente choisit le débit à récupérer et à lire avec DASH.
Dans le cadre du processus de segmentation vidéo, un fichier manifeste XML appelé "description du média" est créé de manière programmatique. Il décrit les ensembles d'adaptation et les représentations, avec des durées et des URL. Un fichier MPD se présente comme suit:
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" mediaPresentationDuration="PT0H3M1.63S" minBufferTime="PT1.5S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011"
type="static">
<Period duration="PT0H3M1.63S" start="PT0S">
<AdaptationSet>
<ContentComponent contentType="video" id="1" />
<Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
<BaseURL>car-20120827-89.mp4</BaseURL>
<SegmentBase indexRange="674-1149">
<Initialization range="0-673" />
</SegmentBase>
</Representation>
<Representation bandwidth="2073921" codecs="avc1.4d401f" height="720" id="2" mimeType="video/mp4" width="1280">
<BaseURL>car-20120827-88.mp4</BaseURL>
<SegmentBase indexRange="708-1183">
<Initialization range="0-707" />
</SegmentBase>
</Representation>
…
</AdaptationSet>
</Period>
</MPD>
(Ce fichier XML est extrait du fichier .mpd utilisé pour le lecteur de démonstration YouTube DASH.)
Selon la spécification DASH, un fichier MPD peut en théorie être utilisé comme source pour une vidéo. Toutefois, pour offrir plus de flexibilité aux développeurs Web, les fournisseurs de navigateurs ont choisi de laisser la prise en charge de DASH aux bibliothèques JavaScript utilisant MSE, comme dash.js. L'implémentation de DASH en JavaScript permet à l'algorithme d'adaptation d'évoluer sans nécessiter de mises à jour du navigateur. L'utilisation de MSE permet également de tester d'autres formats de fichier manifeste et mécanismes de diffusion sans avoir à modifier le navigateur. Le lecteur Shaka de Google implémente un client DASH compatible avec EME.
Le Mozilla Developer Network fournit des instructions sur l'utilisation des outils WebM et de FFmpeg pour segmenter des vidéos et créer un fichier MPD.
Conclusion
L'utilisation du Web pour proposer des contenus audio et vidéo payants croît à très rythme. Il semble que chaque nouvel appareil, qu'il s'agisse d'une tablette, d'une console de jeu, d'une TV connectée ou d'un boîtier décodeur, soit capable de diffuser des contenus multimédias des principaux fournisseurs de contenus via HTTP. Plus de 85 % des navigateurs mobiles et pour ordinateur de bureau sont désormais compatibles avec <video> et <audio>. Cisco estime que la vidéo représentera 80 à 90 % du trafic Internet grand public mondial d'ici 2017. Dans ce contexte, la prise en charge par les navigateurs de la distribution de contenus protégés est susceptible de devenir de plus en plus importante, car les fournisseurs de navigateurs réduisent la prise en charge des API sur lesquelles la plupart des plug-ins multimédias s'appuient.
Documentation complémentaire
Spécifications et normes
Articles
Webinaire sur la TV connectée (partiellement obsolète) What is EME?, par Henri Sivonen Présentation des extensions de source multimédia Flux de test MPEG-DASH : article de blog de la R&D de la BBC
Démonstrations
Démo Clear Key : simpl.info/ck Démo Media Source Extensions (MSE) Shaka Player de Google implémente un client DASH compatible avec EME