할 수 있나요?

암호화된 미디어 확장 프로그램 소개

암호화된 미디어 확장 프로그램은 웹 애플리케이션이 콘텐츠 보호 시스템과 상호작용하여 암호화된 오디오 및 동영상을 재생할 수 있게 하는 API를 제공합니다.

EME는 기본 보호 시스템에 관계없이 모든 브라우저에서 동일한 앱과 암호화된 파일을 사용할 수 있도록 설계되었습니다. 전자는 표준화된 API와 흐름으로 가능하지만 후자는 공통 암호화 개념으로 가능합니다.

EME는 HTMLMediaElement 사양의 확장이므로 이름입니다. '확장 프로그램'이 된다는 것은 EME에 대한 브라우저 지원이 선택 사항이라는 것을 의미합니다. 브라우저가 암호화된 미디어를 지원하지 않으면 암호화된 미디어를 재생할 수 없지만, EME는 HTML 사양을 준수하기 위해 필요하지 않습니다. EME 사양:

EME 구현은 다음과 같은 외부 구성요소를 사용합니다.

  • 키 시스템: 콘텐츠 보호 (DRM) 메커니즘입니다. EME는 Clear Key를 제외하고 키 시스템 자체를 정의하지 않습니다 (자세한 내용은 아래 참조).
  • 콘텐츠 복호화 모듈 (CDM): 암호화된 미디어를 재생할 수 있게 하는 클라이언트 측 소프트웨어 또는 하드웨어 메커니즘입니다. 키 시스템과 마찬가지로, EME는 CDM을 정의하지 않으며, 애플리케이션이 사용 가능한 CDM과 상호 작용할 수 있는 인터페이스를 제공합니다.
  • 라이선스 (키) 서버: CDM과 상호작용하여 미디어 복호화 키를 제공합니다. 라이선스 서버와의 협상은 애플리케이션의 책임입니다.
  • 패키징 서비스: 배포/소비를 위해 미디어를 인코딩하고 암호화합니다.

EME를 사용하는 애플리케이션은 라이선스 서버와 상호작용하여 복호화를 활성화하는 키를 얻지만, 사용자 ID 및 인증은 EME의 일부가 아닙니다. 미디어 재생을 사용 설정하기 위한 키는 (선택적으로) 사용자를 인증한 후에 발생합니다. Netflix와 같은 서비스는 웹 애플리케이션 내에서 사용자를 인증해야 합니다. 사용자가 애플리케이션에 로그인하면 애플리케이션이 사용자의 ID와 권한을 확인합니다.

EME는 어떻게 작동하나요?

다음은 EME 구성요소가 상호작용하는 방식이며, 아래 코드 예에 해당합니다.

  1. 웹 애플리케이션은 하나 이상의 암호화된 스트림이 있는 오디오 또는 동영상을 재생하려고 시도합니다.
  2. 브라우저는 미디어가 암호화되었음을 인식하고 (방법은 아래 상자 참고) 암호화에 관한 미디어에서 가져온 메타데이터 (initData)를 사용하여 encrypted 이벤트를 실행합니다.
  3. 애플리케이션은 encrypted 이벤트를 처리합니다.
    1. 미디어 요소와 연결된 MediaKeys 객체가 없는 경우 먼저 navigator.requestMediaKeySystemAccess()를 사용하여 사용 가능한 키 시스템을 선택하여 어떤 키 시스템을 사용할 수 있는지 확인한 다음 MediaKeySystemAccess 객체를 통해 사용 가능한 키 시스템의 MediaKeys 객체를 만듭니다. MediaKeys 객체의 초기화는 첫 번째 encrypted 이벤트 전에 발생해야 합니다. 라이선스 서버 URL 가져오기는 사용 가능한 키 시스템 선택과는 별개로 앱이 수행합니다. MediaKeys 객체는 오디오 또는 동영상 요소의 미디어를 복호화하는 데 사용할 수 있는 모든 키를 나타냅니다. 이는 CDM 인스턴스를 나타내며, 특히 라이선스 서버에서 키를 얻는 데 사용되는 키 세션을 생성하기 위해 CDM에 대한 액세스를 제공합니다.
    2. MediaKeys 객체를 만들고 나면 미디어 요소에 할당합니다. setMediaKeys()MediaKeys 객체를 HTMLMediaElement와 연결하여 재생 중, 즉 디코딩 중에 키를 사용할 수 있도록 합니다.
  4. 앱은 MediaKeys에서 createSession()를 호출하여 MediaKeySession를 만듭니다. 이렇게 하면 라이선스와 키의 전체 기간을 나타내는 MediaKeySession가 생성됩니다.
  5. 앱은 MediaKeySession에서 generateRequest()를 호출하여 encrypted 핸들러에서 가져온 미디어 데이터를 CDM에 전달하여 라이선스 요청을 생성합니다.
  6. CDM은 라이선스 서버에서 키를 획득하기 위한 요청인 message 이벤트를 실행합니다.
  7. MediaKeySession 객체가 message 이벤트를 수신하고 애플리케이션이 XHR 등을 통해 라이선스 서버에 메시지를 보냅니다.
  8. 애플리케이션이 라이선스 서버로부터 응답을 수신하고 MediaKeySessionupdate() 메서드를 사용하여 데이터를 CDM으로 전달합니다.
  9. CDM은 라이선스의 키를 사용하여 미디어를 복호화합니다. 미디어 요소와 연결된 MediaKey 내의 모든 세션에서 유효한 키를 사용할 수 있습니다. CDM은 키 ID로 색인이 생성된 키와 정책에 액세스합니다.
  10. 미디어 재생이 다시 시작됩니다.

휴...

CDM과 라이선스 서버 간에는 메시지가 여러 개 있을 수 있으며, 이 프로세스의 모든 통신은 브라우저와 애플리케이션에 표시되지 않습니다. 메시지는 CDM과 라이선스 서버에서만 이해할 수 있지만, 앱 레이어에서는 CDM이 전송하는 메시지 유형을 확인할 수 있습니다. 라이선스 요청에는 CDM의 유효성(및 신뢰 관계) 증명과 결과 라이선스에서 콘텐츠 키를 암호화할 때 사용할 키가 포함됩니다.

...하지만 CDM은 실제로 어떤 일을 하나요?

EME 구현은 그 자체로 미디어를 복호화하는 방법을 제공하지 않습니다. 단순히 웹 애플리케이션이 콘텐츠 복호화 모듈과 상호 작용할 수 있도록 API를 제공할 뿐입니다.

CDM이 실제로 하는 일은 EME 사양에 정의되어 있지 않으며 CDM은 미디어의 디코딩 (압축 해제)뿐만 아니라 복호화도 처리할 수 있습니다. 가장 강력한 기능부터 가장 강력한 것까지 CDM 기능에는 여러 가지 잠재적 옵션이 있습니다.

  • 복호화 전용입니다. 일반 미디어 파이프라인(예: <video> 요소)을 사용하여 재생 사용 설정
  • 복호화 및 디코딩, 렌더링을 위해 브라우저에 동영상 프레임 전달
  • 복호화 및 디코딩, 하드웨어 (예: GPU)에서 직접 렌더링

CDM을 웹 앱에 제공하는 방법에는 여러 가지가 있습니다.

  • CDM을 브라우저와 번들로 묶습니다.
  • CDM을 별도로 배포합니다.
  • 운영 체제에 CDM을 빌드합니다.
  • 펌웨어에 CDM을 포함합니다.
  • 하드웨어에 CDM을 포함합니다.

CDM이 제공되는 방식은 EME 사양에 의해 정의되지 않지만, 모든 경우 브라우저가 CDM을 조사하고 노출해야 합니다.

EME는 특정 키 시스템을 요구하지 않습니다. 현재 데스크톱 및 모바일 브라우저 중에서 Chrome은 Widevine을, IE11은 PlayReady를 지원합니다.

라이선스 서버에서 키 가져오기

일반적인 상업적 용도의 경우, 콘텐츠는 패키징 서비스나 도구를 사용하여 암호화 및 인코딩됩니다. 암호화된 미디어를 온라인으로 사용할 수 있게 되면, 웹 클라이언트는 라이선스 서버에서 키 (라이선스에 포함)를 얻고 이 키를 사용하여 콘텐츠를 복호화하고 재생할 수 있습니다.

다음 코드 (사양 예에서 조정)는 애플리케이션이 적절한 키 시스템을 선택하고 라이선스 서버에서 키를 가져오는 방법을 보여줍니다.

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 라이선스 서버에서 키를 얻는 Widevine CDM을 사용하여 브라우저에서 재생될 수 있습니다.

이는 애플리케이션 런타임이 포함된 단일 클라이언트를 포함하여 완전한 수직 스택에서만 작동하는 기존 솔루션과 대조됩니다.

공통 암호화 (CENC)는 ISO BMFF의 보호 체계를 정의하는 ISO 표준으로, 유사한 개념이 WebM에도 적용됩니다.

키 삭제

EME가 DRM 기능을 정의하지는 않지만, 현재 사양에 따르면 EME를 지원하는 모든 브라우저는 지우기 키를 구현해야 합니다. 이 시스템을 사용하면 미디어를 키로 암호화한 다음 이 키를 제공하는 방법으로 미디어를 재생할 수 있습니다. Clear Key는 브라우저에 내장되어 있을 수 있으며, 별도의 복호화 모듈을 사용할 필요가 없습니다.

많은 유형의 상업성 콘텐츠에 사용될 가능성은 낮지만 EME를 지원하는 모든 브라우저에서 Clear Key가 완벽하게 상호 운용이 가능합니다. 또한 라이선스 서버에서 콘텐츠 키를 요청할 필요 없이 EME 구현과 EME를 사용하는 애플리케이션을 테스트하는 데도 유용합니다. simpl.info/ck에 간단한 키 삭제 예가 있습니다. 아래는 라이선스 서버 상호작용 없이 위에 설명된 단계와 동일한 코드를 단계별로 보여줍니다.

// 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에 해당) 다른 솔루션도 개발 중입니다.

Media Source Extensions (MSE)

HTMLMediaElement는 단순한 아름다움을 가진 생명체입니다.

다음과 같이 src URL을 제공하기만 하면 미디어를 로드, 디코딩, 재생할 수 있습니다.

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

Media Source API는 HTMLMediaElement에 대한 확장 기능으로, JavaScript가 동영상의 '청크'에서 재생하기 위한 스트림을 빌드하도록 허용함으로써 미디어 소스를 더욱 세밀하게 제어할 수 있습니다. 이를 통해 적응형 스트리밍 및 타임 시프팅과 같은 기법을 사용할 수 있습니다.

MSE가 EME에 중요한 이유는 무엇인가요? 보호된 콘텐츠를 배포하는 것 외에도 상업적 콘텐츠 제공업체는 네트워크 상태 및 기타 요건에 맞게 콘텐츠 전송을 조정할 수 있어야 하기 때문입니다. 예를 들어 Netflix는 네트워크 상태가 변경됨에 따라 스트림 비트 전송률을 동적으로 변경합니다. EME는 src 속성을 통해 제공된 미디어와 마찬가지로 MSE 구현에서 제공한 미디어 스트림의 재생에서 작동합니다.

다른 비트 전송률로 인코딩된 미디어를 청크하고 재생하는 방법 아래의 DASH 섹션을 참고하세요.

MSE의 작동 방식은 simpl.info/mse에서 확인할 수 있습니다. 이 예에서는 WebM 동영상이 File API를 사용하여 5개의 청크로 분할됩니다. 프로덕션 애플리케이션에서 동영상 청크는 Ajax를 통해 검색됩니다.

먼저 SourceBuffer가 생성됩니다.

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

그런 다음 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);
  }
};

MSE에 대한 자세한 내용은 HTML5 Rocks 도움말을 참조하세요.

HTTP 동적 적응형 스트리밍 (DASH)

멀티 디바이스, 멀티 플랫폼, 모바일 - 뭐든 웹은 연결 상태가 변하는 환경에서 종종 발생합니다. 동적 적응형 게재는 다양한 기기가 사용되는 환경에서 대역폭의 제약과 변동성에 대처하는 데 매우 중요합니다.

DASH (MPEG-DASH라고도 함)는 스트리밍과 다운로드 모두에서 불안정한 환경에서 최상의 미디어 전송을 지원하도록 설계되었습니다. Apple의 HTTP Live Streaming (HLS) 및 Microsoft의 Smooth Streaming과 같은 다른 여러 기술도 유사한 기능을 제공하지만, DASH는 개방형 표준을 기반으로 하는 HTTP를 통한 적응형 비트 전송률 스트리밍을 위한 유일한 방법입니다. DASH는 이미 YouTube 등의 사이트에서 사용 중입니다.

EME 및 MSE와는 어떤 관계가 있나요? MSE 기반 DASH 구현은 기존 HTTP 인프라를 사용하여 매니페스트를 파싱하고, 적절한 비트 전송률로 동영상 세그먼트를 다운로드하고, 배가 고파지면 동영상 요소에 피드할 수 있습니다.

즉, DASH를 사용하면 상업용 콘텐츠 제공업체가 보호된 콘텐츠의 가변 품질 스트리밍을 수행할 수 있습니다.

DASH는 주석에 안내된 대로 실행합니다.

  • 동적: 변화하는 조건에 반응합니다.
  • 적응형: 적절한 오디오 또는 동영상 비트 전송률을 제공하도록 조정됩니다.
  • 스트리밍: 다운로드와 스트리밍이 모두 가능합니다.
  • HTTP: 기존 스트리밍 서버의 단점 없이 HTTP를 활용하여 콘텐츠를 전송할 수 있습니다.

BBC는 DASH를 사용하여 테스트 스트림을 제공하기 시작했습니다.

요약:

  1. 미디어는 다양한 비트 전송률로 인코딩됩니다.
  2. 다양한 비트 전송률 파일은 HTTP 서버에서 제공됩니다.
  3. 클라이언트 웹 앱이 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로 사용할 수 있습니다. 그러나 웹 개발자에게 더 많은 유연성을 제공하기 위해 브라우저 공급업체는 dash.js와 같은 MSE를 사용하는 JavaScript 라이브러리에 DASH 지원을 그대로 두기로 했습니다. 자바스크립트에서 DASH를 구현하면 브라우저 업데이트 없이도 적응 알고리즘이 진화할 수 있습니다. 또한 MSE를 사용하면 브라우저를 변경하지 않고도 대체 매니페스트 형식과 전송 메커니즘을 실험할 수 있습니다. Google의 Shaka Player는 EME 지원을 통해 DASH 클라이언트를 구현합니다.

Mozilla Developer Network에서 WebM 도구 및 FFmpeg를 사용하여 동영상을 분할하고 MPD를 빌드하는 방법을 확인할 수 있습니다.

결론

유료 동영상 및 오디오를 전송하기 위해 웹의 사용이 급격한 속도로 증가하고 있습니다. 태블릿, 게임 콘솔, 스마트 TV 또는 셋톱 박스 등 모든 새 기기는 HTTP를 통해 주요 콘텐츠 제공업체의 미디어를 스트리밍할 수 있습니다. 현재 모바일 및 데스크톱 브라우저의 85% 이상에서 <video><audio>를 지원하고 있으며, Cisco의 예측에 따르면 2017년까지 동영상이 전 세계 소비자 인터넷 트래픽의 80~90%에서 차지할 것으로 예상됩니다. 이러한 맥락에서, 브라우저 공급업체가 대부분의 미디어 플러그인이 사용하는 API에 대한 지원을 축소함에 따라 보호된 콘텐츠 배포에 대한 브라우저 지원이 점점 더 중요해질 것으로 예상됩니다.

추가 자료

사양 및 표준

기사