EME WTF mi?

Şifrelenmiş Medya Uzantılarına giriş

Şifrelenmiş Medya Uzantıları, şifrelenmiş ses ve videonun oynatılmasına izin vermek üzere web uygulamalarının içerik koruma sistemleriyle etkileşime girmesini sağlayan bir API sağlar.

EME, temel koruma sisteminden bağımsız olarak aynı uygulamanın ve şifrelenmiş dosyaların tüm tarayıcılarda kullanılmasını sağlayacak şekilde tasarlanmıştır. Birincisi standart API ve akış, ikincisi ise Ortak Şifreleme kavramıyla mümkün hale gelir.

EME, HTMLMediaElement spesifikasyonunun bir uzantısıdır. Bu nedenle adı. "Uzantı" olmak, EME için tarayıcı desteğinin isteğe bağlı olduğu anlamına gelir: Tarayıcı şifrelenmiş medyayı desteklemiyorsa şifrelenmiş medya oynatamaz, ancak HTML spesifikasyon uyumluluğu için EME gerekli değildir. EME spesifikasyonundan:

EME uygulamalarında aşağıdaki harici bileşenler kullanılır:

  • Anahtar Sistemi: İçerik koruma (DRM) mekanizması. EME, Clear Key dışında Key Systems'ın kendisini tanımlamaz (aşağıda bununla ilgili daha fazla bilgi verilmiştir).
  • İçerik Şifre Çözme Modülü (CDM): Şifrelenmiş medyanın oynatılmasını sağlayan istemci tarafı bir yazılım veya donanım mekanizmasıdır. Key Systems'ta olduğu gibi, EME de herhangi bir CDM tanımlamaz, ancak uygulamaların kullanılabilir CDM'lerle etkileşime geçmesi için bir arayüz sağlar.
  • Lisans (Anahtar) sunucusu: Medyanın şifresini çözecek anahtarlar sağlamak için bir CDM ile etkileşim kurar. Lisans sunucusuyla yapılan pazarlık, uygulamanın sorumluluğundadır.
  • Paketleme hizmeti: Medyaları dağıtım/tüketim için kodlar ve şifreler.

EME kullanan bir uygulamanın, şifre çözmeyi etkinleştirmek için anahtarları almak üzere lisans sunucusuyla etkileşimde bulunduğunu ancak kullanıcı kimliği ve kimlik doğrulamasının EME'nin bir parçası olmadığını unutmayın. Medya oynatmayı etkinleştirmek için tuşlar, kullanıcının kimliği doğrulandıktan sonra (isteğe bağlı olarak) alınır. Netflix gibi hizmetler, kullanıcıların kimliklerini web uygulamaları içinden doğrulamalıdır: Bir kullanıcı uygulamada oturum açtığında, kullanıcının kimliğini ve ayrıcalıkları uygulama tarafından belirlenir.

EME nasıl çalışır?

Aşağıda, aşağıdaki kod örneğine karşılık gelen EME bileşenlerinin nasıl etkileşime geçtiği açıklanmaktadır:

  1. Bir web uygulaması, bir veya daha fazla şifrelenmiş akışa sahip ses veya videoyu oynatmaya çalışır.
  2. Tarayıcı, medyanın şifrelendiğini algılar (bunun nasıl olduğunu öğrenmek için aşağıdaki kutuya bakın) ve şifrelemeyle ilgili medyadan alınan meta verileri (initData) içeren bir encrypted etkinliği tetikler.
  3. Uygulama encrypted etkinliğini işler:
    1. Medya öğesiyle hiçbir MediaKeys nesnesi ilişkilendirilmediyse önce hangi Anahtar Sistemlerinin kullanılabilir olduğunu kontrol etmek için navigator.requestMediaKeySystemAccess() kullanarak kullanılabilir bir Anahtar Sistemi seçin, ardından MediaKeySystemAccess nesnesi aracılığıyla kullanılabilir bir Anahtar Sistemi için MediaKeys nesnesi oluşturun. MediaKeys nesnesinin başlatılmasının ilk encrypted etkinliğinden önce gerçekleşmesi gerektiğini unutmayın. Uygulama, lisans sunucusu URL'sini kullanılabilir bir anahtar sistemi seçilmeden bağımsız olarak alır. MediaKeys nesnesi, bir ses veya video öğesindeki medyanın şifresini çözmek için kullanılabilen tüm anahtarları temsil eder. Bir CDM örneğini temsil eder ve özellikle lisans sunucusundan anahtar almak için kullanılan anahtar oturumları oluşturmak üzere CDM'ye erişim sağlar.
    2. MediaKeys nesnesi oluşturulduktan sonra bunu medya öğesine atayın: setMediaKeys(), MediaKeys nesnesini bir HTMLMediaElement ile ilişkilendirir.Böylece, anahtarların oynatma sırasında (ör. kod çözme sırasında) kullanılabilmesi için.
  4. Uygulama, MediaKeys üzerinde createSession() çağrısı yaparak bir MediaKeySession oluşturur. Bu işlem, bir lisansın ve anahtarlarının kullanım ömrünü temsil eden bir MediaKeySession oluşturur.
  5. Uygulama, MediaKeySession üzerinde generateRequest() yöntemini çağırarak encrypted işleyicisinde elde edilen medya verilerini CDM'ye ileterek bir lisans isteği oluşturur.
  6. CDM, bir message etkinliği tetikler: bu etkinlik, lisans sunucusundan anahtar alma isteğidir.
  7. MediaKeySession nesnesi, message etkinliğini alır ve uygulama, lisans sunucusuna bir mesaj gönderir (örneğin, XHR aracılığıyla).
  8. Uygulama, lisans sunucusundan bir yanıt alır ve MediaKeySession öğesinin update() yöntemini kullanarak verileri CDM'ye iletir.
  9. CDM, lisanstaki anahtarları kullanarak medyanın şifresini çözer. Medya öğesiyle ilişkili MediaKey içindeki herhangi bir oturumdan geçerli bir anahtar kullanılabilir. CDM, Anahtar Kimliğine göre dizine eklenen anahtara ve politikaya erişir.
  10. Medya oynatma devam ettiriliyor.

Neyse...

CDM ile lisans sunucusu arasında birden fazla mesaj olabileceğini ve bu süreçteki tüm iletişimlerin tarayıcı ve uygulama için opak olduğunu unutmayın. Mesajlar yalnızca CDM ve lisans sunucusu tarafından anlaşılsa da CDM'nin gönderdiği mesaj türünü uygulama katmanı görebilir. Lisans isteği, CDM'nin geçerliliğine (ve güven ilişkisine) dair kanıtın yanı sıra oluşturulan lisanstaki içerik anahtarlarını şifrelerken kullanılacak bir anahtar içerir.

...ama CDM'ler gerçekte ne yapar?

EME uygulaması kendi başına medyanın şifresini çözmek için bir yol sağlamaz, yalnızca bir web uygulamasının İçerik Şifre Çözme Modülleriyle etkileşime girmesi için bir API sağlar.

CDM'lerin gerçekte ne yaptığı, EME spesifikasyonunda tanımlanmamıştır ve CDM, medyanın şifresini çözmeyi (sıkıştırmayı çözme) ve şifre çözme işlemlerini gerçekleştirebilir. CDM işlevi için, en az güçlü olandan en güçlü olana doğru birkaç olası seçenek vardır:

  • Yalnızca şifre çözme: Normal medya ardışık düzeni kullanılarak (ör. <video> öğesi aracılığıyla) oynatma etkinleştirilir.
  • Şifre çözme ve kod çözme, video karelerini oluşturma işlemi için tarayıcıya iletme.
  • Şifre çözme ve kod çözme, doğrudan donanımda oluşturma (örneğin, GPU).

Bir CDM'yi bir web uygulaması için kullanılabilir hale getirmenin birden çok yolu vardır:

  • Tarayıcıyla bir CDM'yi gruplandırın.
  • CDM'yi ayrı olarak dağıtın.
  • İşletim sistemine bir CDM ekleyin.
  • Donanım yazılımına bir CDM ekleyin.
  • Donanıma bir CDM yerleştirin.

Bir CDM'nin nasıl kullanıma sunulduğu, EME spesifikasyonunda tanımlanmamıştır, ancak her durumda CDM'yi inceleyip göstermekten tarayıcı sorumludur.

EME belirli bir anahtar sistemini zorunlu kılmaz. Mevcut masaüstü ve mobil tarayıcılarda Chrome, Widevine'i, IE11 ise PlayReady'yi destekler.

Lisans sunucusundan anahtar alma

Tipik ticari kullanımda içerik bir paketleme hizmeti veya aracı kullanılarak şifrelenir ve kodlanır. Şifrelenmiş medya çevrimiçi olarak kullanıma sunulduktan sonra, web istemcisi lisans sunucusundan bir anahtar (lisans içinde yer alır) alabilir ve bu anahtarı içeriğin şifresinin çözülmesini ve oynatılmasını sağlamak için kullanabilir.

Spesifikasyon örneklerinden uyarlanmış aşağıdaki kod, bir uygulamanın nasıl uygun anahtar sistemini seçebileceğini ve lisans sunucusundan nasıl anahtar alabileceğini gösterir.

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

Ortak Şifreleme

Yaygın Şifreleme çözümleri, içerik sağlayıcıların içeriklerini container/codec başına bir kez şifrelemesine ve paketlemesine ve bunları çeşitli Anahtar Sistemleri, CDM'ler ve istemcilerle, yani Ortak Şifrelemeyi destekleyen tüm CDM'lerle kullanmalarına olanak tanır. Örneğin, Playready kullanılarak paketlenen bir video, Widevine lisans sunucusundan bir anahtar alan Widevine CDM kullanılarak tarayıcıda oynatılabilir.

Bu, genellikle bir uygulama çalışma zamanı da içeren tek bir istemci de dahil olmak üzere yalnızca tam bir dikey yığınla çalışan eski çözümlerin tersidir.

Ortak Şifreleme (CENC), ISO BMFF için koruma şemasını tanımlayan bir ISO standardıdır. Benzer bir kavram WebM için de geçerlidir.

Anahtarı Temizle

EME, DRM işlevini tanımlamasa da, spesifikasyon şu anda EME'yi destekleyen tüm tarayıcıların Temizle Anahtarı uygulamasını zorunlu tutmaktadır. Bu sistemde medya bir anahtarla şifrelenebilir ve daha sonra yalnızca bu anahtarı sağlayarak oynatılabilir. Temizleme Anahtarı tarayıcıya yerleşik olabilir: Ayrı bir şifre çözme modülü kullanılmasını gerektirmez.

Birçok ticari içerik türünde kullanılmasa da, Clear Key (EME'yi destekleyen tüm tarayıcılarda) tamamen birlikte çalışabilir. Ayrıca, EME uygulamalarını ve EME kullanan uygulamaları, lisans sunucusundan içerik anahtarı istemeye gerek kalmadan test etmek için de kullanışlıdır. simpl.info/ck adresinde basit bir Clear Key örneği bulabilirsiniz. Lisans sunucusu etkileşimi olmaksızın, yukarıda açıklanan adımlarla paralellik gösteren kodun adım adım açıklamalı kılavuzunu aşağıda bulabilirsiniz.

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

Bu kodu test etmek için, oynatmak üzere şifrelenmiş bir videonun olması gerekir. Temizleme Anahtarı ile kullanılacak bir video, WebM için webm_crypt talimatlarına göre şifrelenebilir. Ticari hizmetler de mevcuttur (en azından ISO BMFF/MP4 için) ve başka çözümler geliştirilmektedir.

Medya Kaynağı Uzantıları (MSE)

HTMLMediaElement basit güzelliğe sahip bir yaratık.

Yalnızca bir src URL'si sağlayarak medyayı yükleyebilir, kodunu çözebilir ve oynatabiliriz:

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

Medya Kaynağı API'sı, JavaScript'in video "parçalarından" oynatmak üzere akışlar oluşturmasına izin vererek medya kaynağı üzerinde daha hassas bir denetim sağlayan HTMLMediaElement uzantısıdır. Bu da uyarlanabilir akış ve zaman değiştirme gibi teknikleri mümkün kılar.

MSE, EME için neden önemlidir? Çünkü ticari içerik sağlayıcıları, korunan içeriklerin dağıtımına ek olarak içerik yayınlamayı ağ koşullarına ve diğer şartlara göre uyarlayabilmelidir. Örneğin Netflix, ağ koşulları değiştikçe yayın bit hızını dinamik olarak değiştirir. EME, bir src özelliği aracılığıyla sağlanan medyada olduğu gibi, MSE uygulaması tarafından sağlanan medya akışlarının oynatılmasıyla çalışır.

Farklı bit hızlarında kodlanmış medya nasıl parçalanır ve oynatılır? Aşağıdaki DASH bölümüne bakın.

MSE'yi simpl.info/mse adresinde çalışırken görebilirsiniz. Bu örnekte, bir WebM videosu Dosya API'ları kullanılarak beş bölüme ayrılmıştır. Bir üretim uygulamasında, video parçaları Ajax aracılığıyla alınır.

İlk olarak bir SourceBuffer oluşturulur:

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

Daha sonra tüm film, insertBuffer() yöntemi kullanılarak her bir parçaya eklenerek bir video öğesine 'yayınlanır':

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 hakkında daha fazla bilgiyi HTML5 Rocks makalesinde bulabilirsiniz.

HTTP üzerinden Dinamik Adaptif Akış (DASH)

Çoklu cihaz, çoklu platform, mobil. Adı ne olursa olsun, web genellikle değişebilen bağlantı koşulları altında yaşanır. Dinamik, uyarlanabilir yayın, çok cihazlı dünyada bant genişliği kısıtlamalarıyla ve değişkenlikle başa çıkmak açısından çok önemlidir.

DASH (MPEG-DASH olarak da bilinir), hem akış hem de indirme için kesintili bir ortamda mümkün olan en iyi medya yayınını sağlamak üzere tasarlanmıştır. Apple'ın HTTP Canlı Akışı (HLS) ve Microsoft'un Smooth Streaming gibi özellikleri de benzer şekilde bir çok teknolojiden yararlanmaktadır. Ancak DASH açık standarda dayalı olan HTTP üzerinden uyarlanabilir bit hızı akışı için kullanılan tek yöntemdir. DASH, YouTube gibi siteler tarafından zaten kullanılıyor.

Bunun EME ve MSE ile ilgisi nedir? MSE tabanlı DASH uygulamaları bir manifesti ayrıştırabilir, video segmentlerini uygun bir bit hızında indirebilir ve acıktığında, mevcut HTTP altyapısını kullanarak bunları bir video öğesine besleyebilir.

Başka bir deyişle DASH, ticari içerik sağlayıcılarının korunan içeriğin uyumlu akışını gerçekleştirmesini sağlar.

DASH ekranda ne diyor?

  • Dinamik: Değişen koşullara tepki verir.
  • Uyarlanabilir: Uygun bir ses veya video bit hızı sağlamak için uyarlanır.
  • Yayın: Hem akış olarak hem de video indirmeye olanak tanır.
  • HTTP: Geleneksel akış sunucusunun dezavantajları olmadan HTTP avantajıyla içerik yayınlamayı sağlar.

BBC, DASH'i kullanarak test akışları sağlamaya başladı:

Özetlemek gerekirse:

  1. Medya, farklı bit hızlarında kodlanmış.
  2. Farklı bit hızı dosyaları bir HTTP sunucusundan kullanılabilir.
  3. DASH ile alınacak ve oynatılacak bit hızını istemci web uygulaması seçer.

Video segmentasyon sürecinin bir parçası olarak Medya Sunumu Açıklaması (MPD) olarak bilinen bir XML manifesti programatik olarak oluşturulur. Bu, Uyarlama Kümelerini ve Gösterimlerini süreler ve URL'lerle açıklar. Bir MPD şuna benzer:

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

(Bu XML, YouTube DASH demo oynatıcısı için kullanılan .mpd dosyasından alınmıştır.

DASH spesifikasyonuna göre MPD dosyaları teoride videoların src öğesi olarak kullanılabilir. Ancak web geliştiricilerine daha fazla esneklik sağlamak için tarayıcı tedarikçileri, DASH desteğini dash.js gibi MSE kullanan JavaScript kitaplıklarına bırakmayı tercih etti. DASH'in JavaScript'te uygulanması, uyarlama algoritmasının tarayıcı güncellemeleri gerektirmeden gelişmesine olanak tanır. MSE'nin kullanılması, tarayıcı değişikliği gerektirmeden alternatif manifest biçimleri ve yayınlama mekanizmalarıyla denemeler yapılmasına da olanak tanır. Google'ın Shaka Player, EME destekli bir DASH istemcisi uygular.

Mozilla Geliştirici Ağı'nda videoyu segmentlere ayırmak ve bir MPD oluşturmak için WebM araçlarının ve FFmpeg'in nasıl kullanılacağı ile ilgili talimatlar bulunmaktadır.

Sonuç

Ücretli video ve işitsel içerik sunmak için web'in kullanımı muazzam bir hızla artıyor. İster tablet, oyun konsolu, bağlı TV, ister set üstü kutu olsun her yeni cihaz, büyük içerik sağlayıcılarından HTTP üzerinden medya akışı yapabiliyor gibi görünüyor. Mobil ve masaüstü tarayıcıların %85'inden fazlası artık <video> ve <audio>'yi desteklemektedir. Cisco, Cisco, 2017 yılına kadar videonun global tüketici internet trafiğinin yüzde 80 ila 90'ını desteklemektedir. Bu bağlamda, tarayıcı tedarikçilerinin çoğu medya eklentisinin ihtiyaç duyduğu API'lere yönelik desteğini azalttığı için korunan içerik dağıtımına yönelik tarayıcı desteğinin önemi giderek artıyor.

Daha fazla bilgi

Özellikler ve standartlar

Makaleler