EME WTF?

Pengantar Ekstensi Media Terenkripsi

Ekstensi Media Terenkripsi menyediakan API yang memungkinkan aplikasi web berinteraksi dengan sistem perlindungan konten, untuk memungkinkan pemutaran audio dan video yang dienkripsi.

EME didesain untuk memungkinkan aplikasi yang sama dan file terenkripsi digunakan di browser apa pun, terlepas dari sistem perlindungan yang mendasarinya. Yang pertama dimungkinkan oleh API dan alur yang terstandardisasi, sedangkan yang kedua dimungkinkan oleh konsep Enkripsi Umum.

EME adalah ekstensi dari spesifikasi HTMLMediaElement sehingga namanya. Menjadi 'ekstensi' berarti bahwa dukungan browser untuk EME bersifat opsional: jika browser tidak mendukung media terenkripsi, browser tidak akan dapat memutar media terenkripsi, tetapi EME tidak diperlukan untuk kepatuhan spesifikasi HTML. Dari spesifikasi EME:

Implementasi EME menggunakan komponen eksternal berikut:

  • Sistem Kunci: Mekanisme perlindungan konten (DRM). EME tidak mendefinisikan Sistem Kunci itu sendiri, selain {i>Clear Key<i} (lebih lanjut tentang itu di bawah).
  • Modul Dekripsi Konten (CDM): Mekanisme hardware atau software sisi klien yang memungkinkan pemutaran media terenkripsi. Seperti Key Systems, EME tidak mendefinisikan CDM, namun menyediakan antarmuka bagi aplikasi untuk berinteraksi dengan CDM yang tersedia.
  • Server lisensi (Kunci): Berinteraksi dengan CDM untuk menyediakan kunci untuk mendekripsi media. Negosiasi dengan server lisensi adalah tanggung jawab aplikasi.
  • Layanan pengemasan: Mengenkode dan mengenkripsi media untuk distribusi/penggunaan.

Perhatikan bahwa aplikasi yang menggunakan EME berinteraksi dengan server lisensi guna mendapatkan kunci untuk mengaktifkan dekripsi, tetapi identitas dan autentikasi pengguna bukan bagian dari EME. Pengambilan kunci untuk mengaktifkan pemutaran media dilakukan setelah (opsional) mengautentikasi pengguna. Layanan seperti Netflix harus mengautentikasi pengguna dalam aplikasi webnya: saat pengguna masuk ke aplikasi, aplikasi tersebut akan menentukan identitas dan hak istimewa pengguna.

Bagaimana cara kerja EME?

Berikut cara komponen EME berinteraksi, sesuai dengan contoh kode di bawah ini:

  1. Aplikasi web mencoba memutar audio atau video yang memiliki satu atau beberapa streaming yang dienkripsi.
  2. Browser mengetahui bahwa media dienkripsi (lihat kotak di bawah untuk mengetahui bagaimana hal itu terjadi) dan mengaktifkan peristiwa encrypted dengan metadata (initData) yang diperoleh dari media tentang enkripsi tersebut.
  3. Aplikasi menangani peristiwa encrypted:
    1. Jika tidak ada objek MediaKeys yang dikaitkan dengan elemen media, pilih Sistem Kunci yang tersedia terlebih dahulu dengan menggunakan navigator.requestMediaKeySystemAccess() untuk memeriksa Sistem Kunci apa yang tersedia, lalu buat objek MediaKeys untuk Sistem Kunci yang tersedia melalui objek MediaKeySystemAccess. Perhatikan bahwa inisialisasi objek MediaKeys harus terjadi sebelum peristiwa encrypted pertama. Mendapatkan URL server lisensi dilakukan oleh aplikasi secara terpisah dari memilih sistem kunci yang tersedia. Objek MediaKeys mewakili semua kunci yang tersedia untuk mendekripsi media untuk elemen audio atau video. Layanan ini mewakili instance CDM dan memberikan akses ke CDM, khususnya untuk membuat sesi kunci, yang digunakan untuk mendapatkan kunci dari server lisensi.
    2. Setelah objek MediaKeys dibuat, tetapkan objek tersebut ke elemen media: setMediaKeys() mengaitkan objek MediaKeys dengan HTMLMediaElement, sehingga kuncinya dapat digunakan selama pemutaran, yaitu selama decoding.
  4. Aplikasi membuat MediaKeySession dengan memanggil createSession() pada MediaKeys. Tindakan ini akan membuat MediaKeySession, yang mewakili masa aktif lisensi dan kuncinya.
  5. Aplikasi membuat permintaan lisensi dengan meneruskan data media yang diperoleh di pengendali encrypted ke CDM, dengan memanggil generateRequest() pada MediaKeySession.
  6. CDM mengaktifkan peristiwa message: permintaan untuk mendapatkan kunci dari server lisensi.
  7. Objek MediaKeySession menerima peristiwa message dan aplikasi akan mengirim pesan ke server lisensi (misalnya melalui XHR).
  8. Aplikasi akan menerima respons dari server lisensi dan meneruskan data ke CDM menggunakan metode update() dari MediaKeySession.
  9. CDM mendekripsi media menggunakan kunci dalam lisensi. Kunci yang valid dapat digunakan, dari sesi apa pun dalam MediaKey yang terkait dengan elemen media. CDM akan mengakses kunci dan kebijakan, yang diindeks oleh ID Kunci.
  10. Pemutaran media dilanjutkan.

Fiuh...

Perlu diperhatikan bahwa mungkin ada beberapa pesan antara CDM dan server lisensi, dan semua komunikasi dalam proses ini tidak terlihat jelas oleh browser dan aplikasi: pesan hanya dipahami oleh CDM dan server lisensi, meskipun lapisan aplikasi dapat melihat jenis pesan yang dikirim oleh CDM. Permintaan lisensi berisi bukti validitas (dan hubungan kepercayaan) CDM, serta kunci yang akan digunakan saat mengenkripsi kunci konten dalam lisensi yang dihasilkan.

...tetapi apa fungsi CDM?

Implementasi EME dengan sendirinya tidak menyediakan cara untuk mendekripsi media: implementasi tersebut hanya menyediakan API agar aplikasi web dapat berinteraksi dengan Modul Dekripsi Konten.

Apa yang sebenarnya dilakukan CDM tidak ditentukan oleh spesifikasi EME, dan CDM dapat menangani decoding (dekompresi) media serta dekripsi. Dari yang paling tidak hingga yang paling tangguh, ada beberapa opsi potensial untuk fungsi CDM:

  • Khusus dekripsi, yang memungkinkan pemutaran menggunakan pipeline media normal, misalnya melalui elemen <video>.
  • Dekripsi dan decoding, meneruskan frame video ke browser untuk rendering.
  • Mendekripsi dan mendekode, merender secara langsung di hardware (misalnya, GPU).

Ada beberapa cara untuk menyediakan CDM untuk aplikasi web:

  • Membundel CDM dengan browser.
  • Mendistribusikan CDM secara terpisah.
  • Membangun CDM ke dalam sistem operasi.
  • Menyertakan CDM dalam firmware.
  • Menyematkan CDM di hardware.

Cara CDM disediakan tidak ditetapkan oleh spesifikasi EME, tetapi dalam semua kasus, browser bertanggung jawab untuk memeriksa dan mengekspos CDM.

EME tidak mewajibkan Sistem Kunci tertentu; di antara browser desktop dan seluler saat ini, Chrome mendukung Widevine dan IE11 mendukung PlayReady.

Mendapatkan kunci dari server lisensi

Dalam penggunaan komersial biasa, konten akan dienkripsi dan dienkode menggunakan layanan atau alat pengemasan. Setelah media terenkripsi tersedia secara online, klien web bisa mendapatkan kunci (yang terdapat dalam lisensi) dari server lisensi dan menggunakan kunci tersebut untuk mengaktifkan dekripsi dan pemutaran konten.

Kode berikut (diadaptasi dari contoh spesifikasi) menunjukkan cara aplikasi memilih sistem kunci yang sesuai dan mendapatkan kunci dari server lisensi.

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

Enkripsi Umum

Solusi Enkripsi umum memungkinkan penyedia konten mengenkripsi dan mengemas kontennya sekali per container/codec dan menggunakannya dengan berbagai Sistem Kunci, CDM, dan klien: yaitu, CDM apa pun yang mendukung Enkripsi Umum. Misalnya, video yang dikemas menggunakan Playsiap dapat diputar kembali di browser menggunakan Widevine CDM yang mendapatkan kunci dari server lisensi Widevine.

Hal ini berbeda dengan solusi lama yang hanya akan berfungsi dengan stack vertikal lengkap, termasuk satu klien yang sering kali juga menyertakan runtime aplikasi.

Common Encryption (CENC) adalah standar ISO yang menentukan skema perlindungan untuk ISO BMFF; konsep serupa berlaku untuk WebM.

Hapus Kunci

Meskipun EME tidak mendefinisikan fungsi DRM, spesifikasi tersebut saat ini mewajibkan semua browser yang mendukung EME harus mengimplementasikan Clear Key. Dengan menggunakan sistem ini, media dapat dienkripsi dengan kunci, lalu diputar dengan menyediakan kunci tersebut. Clear Key dapat dibangun ke dalam browser: tidak memerlukan penggunaan modul dekripsi terpisah.

Meskipun tidak mungkin digunakan untuk berbagai jenis konten komersial, Clear Key dapat dioperasikan sepenuhnya di semua browser yang mendukung EME. Kunci konten juga berguna untuk menguji implementasi EME, dan aplikasi yang menggunakan EME, tanpa perlu meminta kunci konten dari server lisensi. Anda dapat melihat contoh Clear Key sederhana di simpl.info/ck. Di bawah ini adalah panduan kode, yang sejajar dengan langkah-langkah yang dijelaskan di atas, meskipun tanpa interaksi server lisensi.

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

Untuk menguji kode ini, Anda memerlukan video terenkripsi untuk diputar. Mengenkripsi video untuk digunakan dengan Clear Key dapat dilakukan untuk WebM sesuai dengan petunjuk webm_crypt. Layanan komersial juga tersedia (setidaknya untuk ISO BMFF/MP4) dan solusi lainnya sedang dikembangkan.

Ekstensi Sumber Media (RKG)

HTMLMediaElement adalah karya yang menampilkan keindahan sederhana.

Kita dapat memuat, mendekode, dan memutar media hanya dengan memberikan URL src:

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

API Sumber Media adalah ekstensi HTMLMediaElement yang memungkinkan kontrol lebih detail atas sumber media, dengan mengizinkan JavaScript membuat streaming untuk pemutaran dari 'bagian' video. Hal ini pada akhirnya memungkinkan teknik seperti streaming adaptif dan pergeseran waktu.

Mengapa MSE penting bagi EME? Karena selain mendistribusikan konten yang dilindungi, penyedia konten komersial harus dapat menyesuaikan penayangan konten dengan kondisi jaringan dan persyaratan lainnya. Netflix, misalnya, secara dinamis mengubah kecepatan bit streaming saat kondisi jaringan berubah. EME berfungsi dengan pemutaran streaming media yang disediakan oleh penerapan MSE, seperti halnya dengan media yang disediakan melalui atribut src.

Bagaimana cara memilah dan memutar media yang dienkode pada kecepatan bit yang berbeda? Lihat bagian DASH di bawah ini.

Anda dapat melihat cara kerja MSE di simpl.info/mse; untuk tujuan contoh ini, video WebM dibagi menjadi lima bagian menggunakan File API. Dalam aplikasi produksi, potongan video akan diambil melalui Ajax.

Pertama-tama, SourceBuffer dibuat:

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

Seluruh film kemudian 'di-streaming' ke elemen video dengan menambahkan setiap potongan menggunakan metode addBuffer():

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

Cari tahu lebih lanjut tentang MSE di artikel HTML5 Rocks.

Streaming Adaptif Dinamis melalui HTTP (DASH)

Multiperangkat, multi-platform, seluler - apa pun namanya, web sering kali dialami dalam kondisi konektivitas yang dapat berubah. Pengiriman yang dinamis dan adaptif sangat penting untuk mengatasi kendala bandwidth dan variabilitas di dunia multi-perangkat.

DASH (alias MPEG-DASH) dirancang untuk memungkinkan pengiriman media terbaik dalam dunia yang tidak stabil, untuk streaming maupun download. Beberapa teknologi lain melakukan hal serupa - seperti HTTP Live Streaming (HLS) Apple dan Smooth Streaming dari Microsoft - tetapi DASH adalah satu-satunya metode streaming kecepatan bit adaptif melalui HTTP yang didasarkan pada standar terbuka. DASH sudah digunakan oleh situs seperti YouTube.

Apa hubungannya dengan EME dan MSE? Penerapan DASH berbasis MSE dapat mengurai manifes, mendownload segmen video dengan kecepatan bit yang sesuai, dan memasukkannya ke elemen video saat sedang lapar menggunakan infrastruktur HTTP yang ada.

Dengan kata lain, DASH memungkinkan penyedia konten komersial untuk melakukan streaming adaptif konten yang dilindungi.

DASH melakukan apa yang dikatakannya di kaleng:

  • Dinamis: merespons perubahan kondisi.
  • Adaptif: beradaptasi untuk memberikan kecepatan bit audio atau video yang sesuai.
  • Streaming: memungkinkan streaming serta download.
  • HTTP: memungkinkan pengiriman konten dengan memanfaatkan HTTP, tanpa kelemahan server streaming tradisional.

BBC mulai menyediakan uji streaming menggunakan DASH:

Ringkasnya:

  1. Media dienkode pada kecepatan bit yang berbeda.
  2. File kecepatan bit yang berbeda tersedia dari server HTTP.
  3. Aplikasi web klien memilih kecepatan bit yang akan diambil dan diputar dengan DASH.

Sebagai bagian dari proses segmentasi video, manifes XML yang dikenal sebagai Media Presentation Description (MPD) dibuat secara terprogram. Ini menjelaskan Kumpulan dan Representasi Adaptasi, dengan durasi dan URL. MPD terlihat seperti ini:

<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 ini diambil dari file .mpd yang digunakan untuk pemutar demo DASH YouTube)

Menurut spesifikasi DASH, file MPD secara teori dapat digunakan sebagai src untuk video. Namun, untuk memberikan lebih banyak fleksibilitas kepada developer web, vendor browser telah memilih untuk membiarkan dukungan DASH hingga library JavaScript yang menggunakan MSE seperti dash.js. Mengimplementasikan DASH di JavaScript memungkinkan algoritma adaptasi berkembang tanpa memerlukan update browser. Penggunaan MSE juga memungkinkan eksperimen dengan format manifes alternatif dan mekanisme pengiriman tanpa memerlukan perubahan browser. Shaka Player Google menerapkan klien DASH dengan dukungan EME.

Mozilla Developer Network memiliki petunjuk cara menggunakan alat WebM dan FFmpeg untuk membuat segmen video dan membuat MPD.

Kesimpulan

Penggunaan web untuk menayangkan video dan audio berbayar berkembang dengan kecepatan yang besar. Tampaknya setiap perangkat baru, baik itu tablet, konsol game, TV yang terhubung, atau dekoder, dapat melakukan streaming media dari penyedia konten utama melalui HTTP. Lebih dari 85% browser seluler dan desktop kini mendukung <video> dan <audio>, dan Cisco memperkirakan video akan menjadi 80 hingga 90 persen traffic internet konsumen global pada tahun 2017. Dalam konteks ini, dukungan browser untuk distribusi konten yang dilindungi kemungkinan akan semakin signifikan karena vendor browser membatasi dukungan untuk API yang diandalkan oleh sebagian besar plugin media.

Bacaan lebih lanjut

Spesifikasi dan standar

Artikel