EME WTF?

Giới thiệu về Tiện ích phương tiện đã mã hoá

Tiện ích phương tiện đã mã hoá cung cấp API cho phép ứng dụng web tương tác với hệ thống bảo vệ nội dung để cho phép phát âm thanh và video được mã hoá.

EME được thiết kế để cho phép sử dụng cùng một ứng dụng và các tệp đã mã hoá trong mọi trình duyệt, bất kể hệ thống bảo vệ cơ bản nào. Dữ liệu đầu tiên có thể thực hiện được nhờ API và quy trình chuẩn hoá, còn quy trình thứ hai được thực hiện nhờ khái niệm Mã hoá chung.

EME là một phần mở rộng cho thông số kỹ thuật của HTMLMediaElement – do đó có tên này. Là một "tiện ích" có nghĩa là trình duyệt không bắt buộc phải hỗ trợ EME: nếu một trình duyệt không hỗ trợ nội dung nghe nhìn đã mã hoá thì trình duyệt đó sẽ không thể phát nội dung nghe nhìn được mã hoá nhưng không bắt buộc phải có EME để tuân thủ các thông số kỹ thuật về HTML. Trong quy cách EME:

Quá trình triển khai EME sử dụng các thành phần bên ngoài sau đây:

  • Hệ thống chính: Cơ chế bảo vệ nội dung (DRM). EME không tự định nghĩa các Hệ thống chính, ngoài Xóa khóa (tìm hiểu thêm ở bên dưới).
  • Mô-đun giải mã nội dung (CDM): Một cơ chế phần mềm hoặc phần mềm phía máy khách cho phép phát nội dung nghe nhìn đã mã hoá. Giống như Hệ thống khoá, EME không định nghĩa bất kỳ CDM nào nhưng cung cấp giao diện để các ứng dụng tương tác với CDM có sẵn.
  • Máy chủ cấp phép (Khoá): Tương tác với một CDM để cung cấp khoá để giải mã nội dung nghe nhìn. Việc thương lượng với máy chủ cấp phép là trách nhiệm của ứng dụng.
  • Dịch vụ đóng gói: Mã hoá và mã hoá nội dung nghe nhìn để phân phối/tiêu thụ.

Lưu ý rằng ứng dụng dùng EME sẽ tương tác với máy chủ cấp phép để lấy khoá cho phép giải mã. Tuy nhiên, danh tính và phương thức xác thực người dùng không thuộc EME. Việc truy xuất khoá để phát nội dung đa phương tiện diễn ra sau khi xác thực người dùng (không bắt buộc). Các dịch vụ như Netflix phải xác thực người dùng trong ứng dụng web của họ: khi người dùng đăng nhập vào ứng dụng, ứng dụng sẽ xác định danh tính và đặc quyền của người dùng.

EME hoạt động như thế nào?

Dưới đây là cách các thành phần của EME tương tác, tương ứng với mã ví dụ bên dưới:

  1. Một ứng dụng web cố gắng phát âm thanh hoặc video có một hoặc nhiều luồng được mã hoá.
  2. Trình duyệt nhận ra rằng nội dung nghe nhìn đã được mã hoá (xem hộp bên dưới để biết cách mã hoá diễn ra) và kích hoạt một sự kiện encrypted có siêu dữ liệu (initData) nhận được từ nội dung nghe nhìn về quá trình mã hoá.
  3. Ứng dụng này xử lý sự kiện encrypted:
    1. Nếu chưa liên kết đối tượng MediaKeys nào với phần tử nội dung đa phương tiện, trước tiên, hãy chọn một Hệ thống khoá có sẵn bằng cách sử dụng navigator.requestMediaKeySystemAccess() để kiểm tra xem Hệ thống khoá nào có sẵn, sau đó tạo đối tượng MediaKeys cho Hệ thống khoá hiện có thông qua đối tượng MediaKeySystemAccess. Lưu ý rằng việc khởi chạy đối tượng MediaKeys phải xảy ra trước sự kiện encrypted đầu tiên. Quá trình lấy URL máy chủ cấp phép được ứng dụng thực hiện độc lập với việc chọn hệ thống khoá có sẵn. Đối tượng MediaKeys đại diện cho tất cả khoá có sẵn để giải mã nội dung nghe nhìn cho một thành phần âm thanh hoặc video. Phiên bản này đại diện cho một phiên bản CDM và cung cấp quyền truy cập vào CDM, đặc biệt là để tạo các phiên chính dùng để lấy khoá từ máy chủ cấp phép.
    2. Sau khi tạo đối tượng MediaKeys, hãy chỉ định đối tượng đó cho phần tử nội dung đa phương tiện: setMediaKeys() liên kết đối tượng MediaKeys với HTMLMediaElement để có thể dùng các khoá của đối tượng đó trong khi phát, tức là trong quá trình giải mã.
  4. Ứng dụng tạo MediaKeySession bằng cách gọi createSession() trên MediaKeys. Thao tác này sẽ tạo một MediaKeySession, đại diện cho thời gian hoạt động của một giấy phép và(các) khoá của giấy phép đó.
  5. Ứng dụng tạo yêu cầu cấp phép bằng cách truyền dữ liệu đa phương tiện thu được trong trình xử lý encrypted tới CDM, bằng cách gọi generateRequest() trên MediaKeySession.
  6. CDM kích hoạt sự kiện message: yêu cầu lấy khoá từ máy chủ cấp phép.
  7. Đối tượng MediaKeySession nhận sự kiện message và ứng dụng gửi thông báo đến máy chủ cấp phép (ví dụ: qua XHR).
  8. Ứng dụng nhận được phản hồi từ máy chủ cấp phép và chuyển dữ liệu tới CDM bằng phương thức update() của MediaKeySession.
  9. CDM giải mã phương tiện bằng các khoá trong giấy phép. Bạn có thể sử dụng khoá hợp lệ từ bất kỳ phiên nào trong MediaKey được liên kết với phần tử nội dung nghe nhìn. CDM sẽ truy cập vào khoá và chính sách, được lập chỉ mục theo Mã khoá.
  10. Quá trình phát nội dung đa phương tiện sẽ tiếp tục.

Phù...

Lưu ý rằng có thể có nhiều thông báo giữa CDM và máy chủ cấp phép và tất cả hoạt động giao tiếp trong quá trình này không rõ ràng đối với trình duyệt và ứng dụng: chỉ CDM và máy chủ cấp phép mới hiểu được thông báo, mặc dù lớp ứng dụng có thể thấy loại thông báo mà CDM đang gửi. Yêu cầu cấp phép chứa bằng chứng về tính hợp lệ (và mối quan hệ tin cậy) của CDM cũng như khoá để sử dụng khi mã hoá(các) khoá nội dung trong giấy phép nhận được.

...nhưng CDM thực sự có chức năng gì?

Bản thân việc triển khai EME không cung cấp cách giải mã nội dung nghe nhìn mà chỉ đơn giản là cung cấp API để ứng dụng web tương tác với Mô-đun giải mã nội dung.

Những gì CDM thực sự làm không được xác định theo thông số kỹ thuật EME và CDM có thể xử lý việc giải mã (giải nén) nội dung nghe nhìn cũng như giải mã. Từ mạnh nhất cho đến mạnh mẽ nhất, có một số tuỳ chọn tiềm năng cho chức năng CDM:

  • Chỉ giải mã, cho phép phát bằng quy trình nội dung nghe nhìn thông thường, chẳng hạn như qua phần tử <video>.
  • Giải mã và giải mã, truyền khung hình video tới trình duyệt để kết xuất.
  • Giải mã và giải mã, kết xuất trực tiếp trong phần cứng (ví dụ: GPU).

Có nhiều cách để cung cấp CDM cho ứng dụng web:

  • Kết hợp một CDM với trình duyệt.
  • Phân phối riêng một CDM.
  • Tích hợp CDM vào hệ điều hành.
  • Đưa CDM vào chương trình cơ sở.
  • Nhúng CDM vào phần cứng.

Cách thức cung cấp CDM không được xác định theo thông số kỹ thuật của EME, nhưng trong mọi trường hợp, trình duyệt sẽ chịu trách nhiệm rà soát và hiển thị CDM.

EME không bắt buộc một Hệ thống khoá cụ thể; trong số các trình duyệt hiện tại dành cho máy tính và thiết bị di động, Chrome hỗ trợ Widevine và IE11 hỗ trợ PlayReady.

Lấy khoá từ máy chủ cấp phép

Khi sử dụng cho mục đích thương mại thông thường, nội dung sẽ được mã hoá và mã hoá bằng một dịch vụ hoặc công cụ đóng gói. Khi nội dung nghe nhìn đã mã hoá có sẵn trực tuyến, ứng dụng web có thể lấy khoá (có trong một giấy phép) từ máy chủ cấp phép và sử dụng khoá đó để giải mã và phát nội dung.

Mã sau đây (được điều chỉnh từ ví dụ về thông số kỹ thuật) cho thấy cách ứng dụng có thể chọn hệ thống khoá thích hợp và lấy khoá từ máy chủ cấp phép.

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

Mã hoá phổ biến

Giải pháp mã hoá phổ biến cho phép nhà cung cấp nội dung mã hoá và đóng gói nội dung của họ một lần cho mỗi vùng chứa/bộ mã hoá và sử dụng nội dung đó với nhiều Hệ thống khoá, CDM và ứng dụng khách, tức là bất kỳ CDM nào có hỗ trợ tính năng Mã hoá chung. Ví dụ: một video được đóng gói bằng Playready có thể được phát lại trong trình duyệt bằng CDM Widevine lấy khoá từ máy chủ cấp phép của Widevine.

Điều này trái ngược với các giải pháp cũ chỉ hoạt động với ngăn xếp dọc hoàn chỉnh, bao gồm cả một ứng dụng thường cũng bao gồm thời gian chạy ứng dụng.

Mã hoá chung (CENC) là một tiêu chuẩn ISO xác định lược đồ bảo vệ cho ISO BMFF; khái niệm tương tự áp dụng cho WebM.

Xoá khoá

Mặc dù EME không định nghĩa chức năng DRM, nhưng thông số kỹ thuật hiện yêu cầu tất cả các trình duyệt hỗ trợ EME phải triển khai Khoá rõ ràng. Khi sử dụng hệ thống này, bạn chỉ cần cung cấp khoá đó để mã hoá nội dung nghe nhìn bằng một khoá rồi phát lại. Có thể tích hợp Xoá Khoá vào trình duyệt: trình duyệt này không yêu cầu sử dụng một mô-đun giải mã riêng.

Mặc dù có thể không được dùng cho nhiều loại nội dung thương mại, nhưng chế độ này hoàn toàn có thể tương tác trên tất cả các trình duyệt hỗ trợ EME. Phiên bản này cũng rất thuận tiện cho việc kiểm thử việc triển khai EME và các ứng dụng sử dụng EME mà không cần yêu cầu khoá nội dung từ máy chủ cấp phép. Bạn có thể xem một ví dụ đơn giản về Xoá Khoá tại simpl.info/ck. Dưới đây là hướng dẫn từng bước về mã, song song với các bước được mô tả ở trên, mặc dù không có sự tương tác của máy chủ cấp phép.

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

Để kiểm tra mã này, bạn cần có một video đã mã hoá để phát. Bạn có thể mã hoá video để sử dụng bằng Xoá Khoá cho WebM theo hướng dẫn trên webm_crypt. Ngoài ra còn có các dịch vụ thương mại (tối thiểu cho ISO BMFF/MP4) và các giải pháp khác đang được phát triển.

Phần mở rộng nguồn nội dung đa phương tiện (MSE)

HTMLMediaElement là một sinh vật mang vẻ đẹp đơn giản.

Chúng tôi có thể tải, giải mã và phát nội dung đa phương tiện chỉ bằng cách cung cấp một URL src:

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

Media Source API là một phần mở rộng cho HTMLMediaElement cho phép kiểm soát chi tiết hơn nguồn nội dung nghe nhìn, bằng cách cho phép JavaScript tạo luồng để phát từ "các đoạn" video. Nhờ vậy, nhà sáng tạo sẽ có thể khai thác các kỹ thuật như phát trực tuyến thích ứng và chuyển đổi thời gian.

Tại sao MSE lại quan trọng đối với EME? Vì ngoài việc phân phối nội dung được bảo vệ, các nhà cung cấp nội dung thương mại phải có khả năng điều chỉnh việc phân phối nội dung cho phù hợp với điều kiện mạng và các yêu cầu khác. Ví dụ: Netflix tự động thay đổi tốc độ bit khi điều kiện mạng thay đổi. EME hoạt động với tính năng phát các luồng nội dung nghe nhìn do triển khai MSE cung cấp, tương tự như với nội dung nghe nhìn được cung cấp qua thuộc tính src.

Cách phân đoạn và phát lại nội dung nghe nhìn được mã hoá ở các tốc độ bit khác nhau? Xem mục DASH bên dưới.

Bạn có thể xem MSE hoạt động tại simpl.info/mse; cho mục đích của ví dụ này, video WebM được chia thành 5 phần bằng API tệp. Trong ứng dụng chính thức, các phần video sẽ được truy xuất thông qua Ajax.

Trước tiên, SourceBuffer được tạo:

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

Sau đó, toàn bộ phim được 'phát trực tuyến' tới một phần tử video bằng cách nối từng đoạn sử dụng phương thức ExtensionBuffer():

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

Tìm hiểu thêm về MSE trong bài viết về HTML5 Rocks.

Truyền phát thích ứng động qua HTTP (DASH)

Nhiều thiết bị, đa nền tảng, thiết bị di động – bất kể bạn gọi là gì, web thường gặp phải trong điều kiện kết nối không thể thay đổi. Phân phối thích ứng, linh động đóng vai trò quan trọng trong việc đối phó với những hạn chế về băng thông và sự biến đổi trong thế giới đa thiết bị.

DASH (còn gọi là MPEG-DASH) được thiết kế để cho phép phân phối nội dung nghe nhìn tốt nhất có thể trong môi trường không ổn định, cho cả hoạt động phát trực tuyến và tải xuống. Một số công nghệ khác cũng có chức năng tương tự, chẳng hạn như Phát trực tuyến dựa trên HTTP (HLS) của Apple và Truyền trực tuyến mượt mà của Microsoft — nhưng DASH là phương thức duy nhất truyền trực tuyến tốc độ bit thích ứng qua HTTP dựa trên tiêu chuẩn mở. DASH đã được các trang web như YouTube sử dụng.

Việc này có liên quan gì đến EME và MSE? Việc triển khai DASH dựa trên MSE có thể phân tích cú pháp tệp kê khai, tải các phân đoạn video xuống ở tốc độ bit thích hợp và đưa chúng vào phần tử video khi phần tử đó đói – bằng cách sử dụng cơ sở hạ tầng HTTP hiện có.

Nói cách khác, DASH cho phép các nhà cung cấp nội dung thương mại thực hiện việc truyền phát thích ứng nội dung được bảo vệ.

DASH có chức năng như sau trên hộp:

  • Linh hoạt: phản hồi các điều kiện thay đổi.
  • Thích ứng: điều chỉnh để cung cấp tốc độ bit âm thanh hoặc video thích hợp.
  • Phát trực tuyến: cho phép phát trực tuyến cũng như tải xuống.
  • HTTP:cho phép phân phối nội dung nhờ ưu thế của HTTP mà không có nhược điểm của máy chủ phát trực tuyến truyền thống.

BBC đã bắt đầu cung cấp luồng thử nghiệm bằng DASH:

Tóm tắt:

  1. Nội dung nghe nhìn được mã hoá ở các tốc độ bit khác nhau.
  2. Các tệp tốc độ bit khác nhau do máy chủ HTTP cung cấp.
  3. Một ứng dụng web khách chọn tốc độ bit để truy xuất và phát lại bằng DASH.

Là một phần của quy trình phân đoạn video, tệp kê khai XML được gọi là Mô tả bản trình bày nội dung nghe nhìn (MPD) được xây dựng theo phương thức lập trình. Phần này mô tả Tập hợp thích ứng và Đại diện, với thời lượng và URL. MPD trông giống như sau:

<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 này được lấy từ tệp .mpd dùng cho trình phát minh hoạ DASH của YouTube)

Theo thông số kỹ thuật của DASH, trên lý thuyết, tệp MPD có thể được dùng làm src cho video. Tuy nhiên, để giúp các nhà phát triển web linh hoạt hơn, các nhà cung cấp trình duyệt đã chọn ngừng hỗ trợ DASH cho tối đa các thư viện JavaScript sử dụng MSE, chẳng hạn như dash.js. Việc triển khai DASH trong JavaScript cho phép thuật toán thích ứng phát triển mà không cần cập nhật trình duyệt. Khi sử dụng MSE, bạn cũng có thể thử nghiệm với các định dạng tệp kê khai và cơ chế phân phối thay thế mà không cần thay đổi trình duyệt. Shaka Player của Google triển khai ứng dụng DASH có hỗ trợ EME.

Mạng Nhà phát triển Mozilla có hướng dẫn về cách sử dụng các công cụ WebM và FFmpeg để phân đoạn video và tạo MPD.

Kết luận

Hoạt động sử dụng web để cung cấp video và âm thanh trả phí đang gia tăng với tỷ lệ rất lớn. Có vẻ như mọi thiết bị mới, cho dù là máy tính bảng, máy chơi trò chơi, TV thông minh hay hộp giải mã tín hiệu số, đều có thể phát trực tuyến nội dung đa phương tiện từ các nhà cung cấp nội dung lớn qua HTTP. Hơn 85% trình duyệt trên thiết bị di động và máy tính hiện hỗ trợ <video><audio>, đồng thời Cisco ước tính rằng video sẽ chiếm 80 đến 90% lưu lượng truy cập Internet của người tiêu dùng trên toàn cầu vào năm 2017. Trong bối cảnh này, sự hỗ trợ của trình duyệt cho hoạt động phân phối nội dung được bảo vệ có thể ngày càng trở nên quan trọng, vì các nhà cung cấp trình duyệt hỗ trợ hạn chế những API mà hầu hết các trình bổ trợ nội dung đa phương tiện đều dựa vào.

Tài liệu đọc thêm

Thông số kỹ thuật và tiêu chuẩn

Bài viết