加密媒体扩展(EME)

[TOC]

加密媒体扩展(Encrypted Media Extensions)提供了一种API,可以使Web应用程序与内容保护系统进行交互,以允许播放加密的音频和视频。

EME旨在使相同的应用程序和加密文件在任何浏览器中使用,而不管底层保护系统如何。前者是通过标准化的API和流程实现的,而后者通过通用加密的概念成为可能 。

EME是HTMLMediaElement规范的扩展,因此取名。作为“扩展”意味着浏览器对EME的支持是可选的:如果浏览器不支持加密的媒体,它将无法播放加密的媒体,但是EME不符合HTML规范。从 EME规范

该提案扩展了 HTMLMediaElement, 提供了API来控制受保护内容的播放。

API支持从简单的清除密钥解密到高价值视频(给定适当的用户代理实现)的用例。许可证/密钥交换由应用程序控制,便于开发支持一系列内容解密和保护技术的强大的回放应用程序。

本规范未定义内容保护或数字版权管理系统。相反,它定义了可以用于发现,选择和与这样的系统以及更简单的内容加密系统交互的通用API。数字版权管理的实施不符合本规范要求:只有Clear Key系统才能被实现为一个共同的基准。

通用API支持一组简单的内容加密功能,将页面作者的身份验证和授权等应用程序功能留下。这是通过要求内容保护系统特定的消息传递由页面介导而不是假设加密系统与许可证或其他服务器之间的带外通信来实现的。

EME实现使用以下外部组件:

  • 关键系统:内容保护(DRM)机制。EME没有定义密钥系统本身,除了清除键(更多关于下文)。

  • 内容解密模块(CDM):支持加密媒体播放的客户端软件或硬件机制。与Key Systems一样,EME还没有定义任何CDM,而是为应用程序提供了与可用CDM进行交互的界面。

  • 许可证(Key)服务器:与CDM进行交互以提供解密媒体的密钥。许可证服务器的协商是应用程序的责任。

  • 包装服务:编码和加密媒体进行分发/消费。

请注意,使用EME的应用程序与许可证服务器交互以获取密钥以启用解密,但用户身份和身份验证不是EME的一部分。在可选地验证用户之后,检索启用媒体播放的键。Netflix等服务必须对其Web应用程序中的用户进行身份验证:用户登录应用程序时,应用程序将确定用户的身份和权限。

EME如何工作?

以下是EME组件的相互作用,与下面代码示例相对应 :

如果有多种格式或编解码器可用,则MediaSource.isTypeSupported()HTMLMediaElement.canPlayType() 都可用于选择正确的格式 。但是,CDM可能只支持浏览器支持未加密内容的一部分。最好在选择格式和编解码器之前协商MediaKeys配置。如果应用程序等待加密的事件,但是MediaKeys显示它无法处理所选的格式/编解码器,那么在不中断播放的情况下切换可能太晚了。

推荐的流程是首先使用MediaKeysSystemAccess.getConfiguration()来协商MediaKey,以查找协商的配置。

如果只有一种格式/编解码器可供选择,那么不需要getConfiguration()。但是,最好先建立MediaKeys。等待加密事件的唯一原因是,如果没有办法知道内容是否被加密,但实际上不太可能。

  1. Web应用程序尝试播放具有一个或多个加密流的音频或视频。

  2. 浏览器会识别媒体是否被加密(请参阅下面的框),并触发加密事件,从媒体获取有关加密的元数据(initData)。

  3. 应用程序处理加密事件:

    1. 如果没有MediaKeys对象已经与媒体元素相关联,首先使用navigator.requestMediaKeySystemAccess()来检查可用的密钥系统,然后通过MediaKeySystemAccess对象为可用密钥系统创建一个MediaKeys对象。请注意,MediaKeys对象的初始化应该发生在第一个加密事件之前。获取许可证服务器URL是由应用程序完成的,而不是选择可用的密钥系统。MediaKeys对象表示可用于解密音频或视频元素的媒体的所有键。它代表CDM实例,并提供对CDM的访问,专门用于创建密钥会话,用于从许可证服务器获取密钥。

    2. MediaKeys对象创建完成后,将其分配给媒体元素:setMediaKeys()将MediaKeys对象与HTMLMediaElement相关联,从而可以在播放过程中使用它的键,即在解码过程中。

  4. 该应用程序通过在MediaKeys上调用createSession()创建一个MediaKeySession。这将创建一个MediaKeySession,它表示许可证的生命周期及其密钥。

  5. 通过在MediaKeySession上调用generateRequest(),通过将加密处理程序中获取的媒体数据传递给CDM来生成许可证请求。

  6. CDM触发消息事件:从许可证服务器获取密钥的请求。

  7. MediaKeySession对象接收消息事件,应用程序向许可证服务器发送消息(例如,通过XHR)。

  8. 应用程序从许可证服务器接收响应,并使用MediaKeySession的update()方法将数据传递给CDM。

  9. CDM使用许可证中的密钥解密媒体。可以使用与媒体元素相关联的MediaKey中的任何会话的有效密钥。CDM将访问按密钥ID索引的密钥和策略。

媒体播放恢复。

浏览器如何知道媒体是否被加密?

该信息在媒体容器文件的元数据中,其格式为ISO BMFF或WebM。对于ISO BMFF,这意味着标题元数据,称为保护方案信息框。WebM使用Matroska ContentEncryption元素,并添加了特定的WebM。为EME特定的注册表中的每个容器提供了指南。

请注意,CDM和许可证服务器之间可能存在多条消息,并且此过程中的所有通信对于浏览器和应用程序都是不透明的:消息仅由CDM和许可证服务器理解,尽管应用层可以看到CDM正在发送 什么类型的消息 。许可证请求包含CDM的有效性(和信任关系)的证明,以及在生成的许可证中加密内容密钥时使用的密钥。

但CDM究竟做了什么呢?

EME实现本身不提供解密媒体的方法:它只是为Web应用程序提供一个API,以便与内容解密模块进行交互。

CDM实际上做了什么不是由EME规范定义的,CDM可以处理媒体的解码(解压缩)以及解密。从至少到最强大的,CDM功能有几个潜在的选择:

  • 仅解密,使用普通媒体流水线进行播放,例如通过<video>元素进行播放。

  • 解密和解码,将视频帧传递到浏览器进行渲染。

  • 解密和解码,直接在硬件中渲染(例如,GPU)。

可以通过多种方法使CDM可用于Web应用程序:

  • 用浏览器捆绑CDM。

  • 分发CDM。

  • 在操作系统中构建CDM。

  • 在固件中加入CDM。

  • 将CDM嵌入硬件。

如何提供CDM不是由EME规范定义的,但在所有情况下,浏览器都负责审核和公开CDM。

EME不要求特定的关键系统; 在目前的桌面和移动浏览器中,Chrome支持Widevine,IE11支持PlayReady。

从许可证服务器获取密钥

在典型的商业用途中,内容将使用包装服务或工具进行加密和编码。一旦加密的媒体可以在线获得,Web客户端可以从许可证服务器获得密钥(包含在许可证中),并使用该密钥来启用内容的解密和回放。

以下代码(从规范示例中改编 )显示了应用程序如何选择适当的密钥系统并从许可证服务器获取密钥。

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')
  );
}

通用加密

通用加密解决方案允许内容提供商对每个容器/编解码器加密和打包其内容一次,并将其与各种密钥系统,CDM和客户端一起使用:即支持通用加密的任何CDM。例如,使用Playready打包的视频可以使用Widevine CDM在浏览器中播放(从一个Widevine许可证服务器获得密钥)。

这与仅适用于完整垂直堆栈的传统解决方案相反,包括应用程序运行时的单个客户端。

公共加密 (CENC)是ISO标准 定义用于ISO BMFF保护方案; 一个类似的概念适用于WebM。

Clear Key

虽然EME没有定义DRM功能,但规范当前要求支持EME的所有浏览器都必须实现Clear Key。使用该系统,媒体可以用密钥加密,然后通过提供该密钥来播放。清除密钥可以内置到浏览器中:它不需要使用单独的解密模块。

虽然不太可能用于许多类型的商业内容,但Clear Key可以在支持EME的所有浏览器中完全互操作。它也适用于测试EME实现以及使用EME的应用程序,而无需从许可证服务器请求内容密钥。simple.info/ck有一个简单的Clear Key示例。以下是代码的演练,与上述步骤相似,尽管没有许可证服务器交互。

// 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]
  }));
}

要测试此代码,您需要加密的视频才能播放。根据webm_crypt指令,可以为WebM加密视频以与Clear Key一起使用。商业服务也可用(至少为ISO BMFF / MP4),其他解决方案正在开发中。

相关技术#1:媒体源扩展(MSE)

HTMLMediaElement 是简约美的东西。

我们可以通过提供src URL来加载,解码和播放媒体:

<video src='foo.webm'></video>

媒体源API是HTMLMediaElement的扩展,可以通过允许JavaScript构建流从“视频块”进行播放,从而对媒体源进行更细粒度的控制。这反过来又实现了自适应流和时移等技术。

为什么MSE对EME很重要?因为除了分发受保护的内容之外,商业内容提供商必须能够适应内容传递到网络条件和其他要求。Netflix,例如,随着网络条件的变化,动态地改变流比特率。EME可以播放由MSE实现提供的媒体流,就像通过src属性提供的媒体一样。

如何分块和播放以不同比特率编码的媒体?请参阅下面DASH部分

你可以在tiny.info/mse看到MSE的行动; 为了本示例的目的,使用File API将WebM视频分成五个块。在生产应用程序中,可以通过Ajax检索大块视频。

首先创建一个SourceBuffer:

var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');

然后通过使用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);
  }
};

MSE底稿中了解有关MSE的更多信息 。

相关技术#2:通过HTTP的动态自适应流(DASH)

多设备,多平台,移动设备 - 无论您称之为什么,网络通常都是在连接变化的条件下经历的。动态,自适应传递对于应对多设备世界中的带宽限制和变异性至关重要。

DASH(又名MPEG-DASH)旨在实现流媒体和下载的片状世界中最好的媒体传输。其他一些技术也做了类似的工作,例如苹果的 HTTP Live Streaming(HLS)和微软的 Smooth Streaming ,但DASH是基于开放标准的通过HTTP进行自适应比特率流的唯一方法。DASH已经在YouTube等网站上使用。

这与EME和MSE有什么关系?基于MSE的DASH实现可以解析清单,以适当的比特率下载视频片段,并在使用现有的HTTP基础设施时将其提供给视频元素。

换句话说,DASH使商业内容提供商能够进行受保护内容的自适应流传输。

DASH说了什么:

  • 动态:响应不断变化的条件。

  • 自适应:适应于提供适当的音频或视频比特率。

  • 传输:允许流式传输以及下载。

  • HTTP:使用HTTP的优势实现内容传送,而没有传统流服务器的缺点。

BBC已经开始使用DASH提供测试流

媒体以不同的比特率编码多次。每个编码称为表示。这些分为多个媒体片段。客户端通过请求片段依次通过HTTP的表示来播放节目。表示可以分组为含有等效内容的表示形式的适应集合。如果客户端希望改变比特率,它可以从当前的适配集中选择一个替代方案,并从该表示开始请求片段。内容以这样的方式进行编码,使客户端可以轻松进行此切换。除了多个媒体片段之外,表示通常还具有初始化片段。这可以被认为是一个标题,包含有关编码,帧大小等的信息。

总结:

  1. 媒体以不同的比特率进行编码。

  2. 不同的比特率文件可从HTTP服务器获得。

  3. 客户端Web应用程序选择使用DASH检索和回放的比特率。

作为视频分段过程的一部分,以编程方式构建了称为媒体演示描述(MPD)的XML清单。这描述了适应性集和表示,具有持续时间和URL。MPD看起来像这样:

<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>

(该XML来自 用于 YouTube DASH演示播放器的.mpd文件。)

根据DASH规范,MPD文件理论上可以用作视频的src。然而,为了给Web开发人员提供更多的灵活性,浏览器供应商已经选择使用MSE(如dash.js)将DASH支持留给JavaScript库。在JavaScript中实现DASH允许自适应算法演变而不需要浏览器更新。使用MSE还可以使用替代的清单格式和传递机制进行实验,而不需要浏览器更改。Google的 Shaka Player实现了一个支持EME的DASH客户端。

Mozilla开发人员网络有 关于如何使用WebM工具和FFmpeg来分割视频并构建MPD的说明。

结论

网络的使用提供付费视频和音频是在不断增长的 巨大率。看来,无论是平板电脑,游戏机,连接电视还是机顶盒,每个新设备都能够通过HTTP流式传输主要内容提供商的媒体。超过85%的移动和桌面浏览器现在支持<video><audio>,而思科估计 2017年,视频将占全球消费者互联网流量80%至90%。在这种情况下,浏览器对受保护内容分发的支持可能越来越重要,因为 浏览器供应商 减少 对大多数媒体插件依赖的API的支持

进一步阅读

规格和标准

文章

演示

Last updated