Présentation des API Encrypted Media Extensions

Les extensions multimédias chiffrées (EME) fournissent une API qui permet aux applications Web d'interagir avec les systèmes de protection du contenu afin de permettre la lecture de contenu audio et vidéo chiffré.

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. La première est rendue possible grâce aux API et au flux standardisés, tandis que la seconde est rendue possible par le concept de Common Encryption.

L'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é avec les spécifications HTML. D'après les spécifications relatives aux EME:

Les implémentations EME utilisent les composants externes suivants :

  • Système de clés : mécanisme de protection du contenu (DRM). La CEM 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 avec les systèmes de clés, la CDM ne définit pas de 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 à des fins de distribution et de consommation.

Notez qu'une application utilisant EME interagit avec un serveur de licence pour obtenir des clés permettant le déchiffrement, mais que l'identité et l'authentification des utilisateurs ne font pas partie d'EME. Les clés permettant la lecture des contenus multimédias sont récupérées après l'authentification (facultative) 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 droits d'accès.

Comment fonctionne l'EME ?

Voici comment les composants de la CEM interagissent, correspondant à l'exemple de code suivant:

  1. Une application Web tente de lire un contenu audio ou vidéo contenant un ou plusieurs flux chiffrés.
  2. 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 encrypted avec des métadonnées (initData) obtenues à partir du contenu multimédia sur le chiffrement.
  3. L'application gère l'événement encrypted :
    1. 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 les systèmes de clés 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 se produire avant le premier événement encrypted. L'obtention d'une URL de serveur de licences est effectuée par l'application 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.
    2. 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.
  4. L'application crée un MediaKeySession en appelant createSession() sur le MediaKeys. Cela crée un MediaKeySession, qui représente la durée de vie d'une licence et de sa ou ses clés.
  5. L'application génère une demande de licence en transmettant les données multimédias obtenues dans le gestionnaire encrypted au CDM, en appelant generateRequest() sur le MediaKeySession.
  6. Le CDM génère un événement message : une requête visant à acquérir une clé auprès d'un serveur de licences.
  7. L'objet MediaKeySession reçoit l'événement message, et l'application envoie un message au serveur de licence (via XHR, par exemple).
  8. 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.
  9. 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 MediaKey associées à l'élément multimédia. Le CDM accédera à la clé et à la stratégie, indexées par ID de clé.
  10. La lecture des contenus multimédias reprend.

Ouf…

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 application puisse voir le type de message envoyé par le CDM. 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.

Ce que font réellement les CDM n’est pas défini par la spécification EME, et un CDM peut gérer le décodage (décompression) des médias ainsi que le déchiffrement. Du moins au plus robuste, il existe plusieurs options 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égrez 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 un usage commercial typique, le contenu est chiffré et encodé à l'aide d'un service ou d'un outil de packaging. Une fois le contenu multimédia chiffré mis en ligne, un client Web peut obtenir une clé (contenant une licence) auprès d'un serveur de licence et l'utiliser pour activer 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="vp9"'}]}];

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 de 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 qui obtient 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.

Common Encryption (CENC) est une norme ISO définissant 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 avec une clé, puis lus simplement en fournissant cette clé. L'option 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 utile pour tester les implémentations EME et les applications qui utilisent EME, sans avoir à demander une clé de contenu à un serveur de licence. Vous trouverez un exemple simple de Clear Key à l'adresse simpl.info/ck. Vous trouverez ci-dessous une procédure de dépannage 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 afin de l'utiliser avec une clé d'effacement pour WebM, conformément aux instructions relatives à webm_crypt. Des services commerciaux sont également disponibles (au moins pour ISO BMFF/MP4) et d'autres solutions sont en cours de développement.

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 de contrôler plus précisément la source multimédia, en permettant à JavaScript de créer des flux de lecture à partir de "segments" de vidéo. Cela permet à son tour d'utiliser 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 des contenus protégés, les fournisseurs de contenus commerciaux doivent pouvoir adapter la diffusion de leurs contenus 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. L'EME fonctionne avec la lecture des flux multimédias fournis par une implémentation MSE, comme avec les contenus 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 MSE en action sur simpl.info/mse. Pour les besoins de cet exemple, une vidéo WebM est divisée en cinq segments à 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 "streamé" vers un élément vidéo en ajoutant chaque segment à 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 l'article HTML5 Rocks.

Streaming adaptatif dynamique sur HTTP (DASH)

Multi-appareil, multi-plate-forme, mobile : quelle que soit la façon dont vous le décrivez, le Web est souvent utilisé dans des conditions de connectivité variables. La diffusion dynamique et adaptative est essentielle pour faire face aux contraintes de bande passante et à la variabilité dans un 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 offrent des résultats similaires, comme HTTP Live Streaming (HLS) et Smooth Streaming de Microsoft, mais DASH est la seule méthode de streaming à débit adaptatif via HTTP qui repose sur une norme ouverte. DASH est déjà utilisé par des sites tels que YouTube.

Quel est le rapport avec l'EME et la 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 lorsqu'il a besoin de plus de données, en utilisant l'infrastructure HTTP existante.

En d'autres termes, DASH permet aux fournisseurs de contenus commerciaux de diffuser des contenus protégés en streaming adaptatif.

DASH fait ce qu'il dit sur la boîte :

  • Dynamique:répond à l'évolution des conditions.
  • 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 classique.

La BBC a commencé à fournir des flux de test avec DASH :

En résumé :

  1. Les contenus multimédias sont encodés à différents débits.
  2. Les différents fichiers de débit sont mis à disposition à partir d'un serveur HTTP.
  3. 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 de la présentation du média, est créé de façon 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 src 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 la technologie EME.

Le Mozilla Developer Network fournit des instructions sur l'utilisation des outils WebM et 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 pour mobile et 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