암호화된 미디어 확장 프로그램(EME)은 웹 애플리케이션이 콘텐츠 보호 시스템과 상호작용하여 암호화된 오디오 및 동영상을 재생할 수 있도록 하는 API를 제공합니다.
EME는 기본 보호 시스템에 관계없이 동일한 앱과 암호화된 파일을 모든 브라우저에서 사용할 수 있도록 설계되었습니다. 전자는 표준화된 API 및 흐름으로 가능하며 후자는 공통 암호화 개념으로 가능합니다.
EME는 HTMLMediaElement
사양의 확장 프로그램이므로 이름이 EME입니다. '확장 프로그램'이라는 것은 EME에 대한 브라우저 지원이 선택사항이라는 의미입니다. 브라우저에서 암호화된 미디어를 지원하지 않으면 암호화된 미디어를 재생할 수 없지만 HTML 사양 준수에는 EME가 필요하지 않습니다. EME 사양:
EME 구현은 다음과 같은 외부 구성요소를 사용합니다.
- 키 시스템: 콘텐츠 보호 (DRM) 메커니즘입니다. EME는 Clear Key를 제외하고 키 시스템 자체를 정의하지 않습니다(자세한 내용은 아래 참고).
- 콘텐츠 복호화 모듈(CDM): 암호화된 미디어의 재생을 지원하는 클라이언트 측 소프트웨어 또는 하드웨어 메커니즘입니다. 키 시스템과 마찬가지로 EME는 어떠한 CDM도 정의하지 않지만 애플리케이션이 사용 가능한 CDM과 상호작용할 수 있는 인터페이스를 제공합니다.
- 라이선스 (키) 서버: CDM과 상호작용하여 미디어 복호화 키를 제공합니다. 라이선스 서버와의 협상은 애플리케이션의 책임입니다.
- 패키징 서비스: 배포/소비를 위해 미디어를 인코딩하고 암호화합니다.
EME를 사용하는 애플리케이션은 라이선스 서버와 상호작용하여 복호화를 사용 설정하는 키를 가져오지만 사용자 ID 및 인증은 EME의 일부가 아닙니다. 미디어 재생을 사용 설정하기 위한 키 검색은 사용자 인증(선택사항) 후에 이루어집니다. Netflix와 같은 서비스는 웹 애플리케이션 내에서 사용자를 인증해야 합니다. 사용자가 애플리케이션에 로그인하면 애플리케이션에서 사용자의 ID와 권한을 결정합니다.
EME는 어떻게 작동하나요?
다음은 다음 코드 예시와 상응하는 EME 구성요소의 상호작용 방식입니다.
- 웹 애플리케이션이 하나 이상의 암호화된 스트림이 포함된 오디오 또는 동영상을 재생하려고 시도합니다.
- 브라우저는 미디어가 암호화되었다는 것을 인식하고(암호화되는 방식은 아래 상자를 참고하세요) 미디어에서 암호화에 관한 메타데이터(
initData
)를 사용하여encrypted
이벤트를 실행합니다. - 애플리케이션이
encrypted
이벤트를 처리합니다.- 미디어 요소에 연결된
MediaKeys
객체가 없는 경우 먼저navigator.requestMediaKeySystemAccess()
를 사용하여 사용 가능한 키 시스템을 확인하여 사용 가능한 키 시스템을 선택한 다음MediaKeySystemAccess
객체를 통해 사용 가능한 키 시스템의MediaKeys
객체를 만듭니다. MediaKeys 객체의 초기화는 첫 번째encrypted
이벤트 전에 이루어져야 합니다. 라이선스 서버 URL은 사용 가능한 키 시스템을 선택하는 것과 관계없이 앱에서 가져옵니다.MediaKeys
객체는 오디오 또는 동영상 요소의 미디어를 복호화하는 데 사용할 수 있는 모든 키를 나타냅니다. 이는 CDM 인스턴스를 나타내며, 특히 라이선스 서버에서 키를 가져오는 데 사용되는 키 세션을 생성하기 위해 CDM에 대한 액세스를 제공합니다. MediaKeys
객체가 생성되면 미디어 요소에 할당합니다.setMediaKeys()
는MediaKeys
객체를 HTMLMediaElement와 연결하므로 재생 중에 키를 사용할 수 있습니다(즉, 디코딩 중에).
- 미디어 요소에 연결된
- 앱은
MediaKeys
에서createSession()
를 호출하여MediaKeySession
를 만듭니다. 이렇게 하면 라이선스와 키의 전체 기간을 나타내는MediaKeySession
이 생성됩니다. - 앱은
MediaKeySession
에서generateRequest()
를 호출하여encrypted
핸들러에서 가져온 미디어 데이터를 CDM에 전달하여 라이선스 요청을 생성합니다. - CDM은 라이선스 서버에서 키를 가져오라는 요청인
message
이벤트를 실행합니다. MediaKeySession
객체가message
이벤트를 수신하고 애플리케이션은 라이선스 서버에 메시지를 전송합니다(예: XHR을 통해).- 애플리케이션은 라이선스 서버로부터 응답을 수신하고
MediaKeySession
의update()
메서드를 사용하여 데이터를 CDM에 전달합니다. - CDM은 라이선스의 키를 사용하여 미디어를 복호화합니다. 미디어 요소와 연결된
MediaKey
내의 모든 세션에서 유효한 키를 사용할 수 있습니다. CDM은 키 ID로 색인이 생성된 키와 정책에 액세스합니다. - 미디어 재생이 재개됩니다.
휴…
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를 구현해야 한다고 규정하고 있습니다. 이 시스템을 사용하면 키로 미디어를 암호화한 후 키를 제공하기만 하면 재생할 수 있습니다. 삭제 키는 브라우저에 내장될 수 있으며, 별도의 복호화 모듈을 사용할 필요가 없습니다.
Clear Key는 많은 유형의 상업용 콘텐츠에 사용되지는 않지만 EME를 지원하는 모든 브라우저에서 완전히 상호 운용됩니다. 라이선스 서버에서 콘텐츠 키를 요청하지 않고도 EME 구현 및 EME를 사용하는 애플리케이션을 테스트하는 데도 유용합니다. simpl.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]
}));
}
이 코드를 테스트하려면 재생할 암호화된 동영상이 필요합니다. Clear Key와 함께 사용할 동영상을 암호화하려면 webm_crypt 안내에 따라 WebM을 암호화하면 됩니다. 상용 서비스도 제공되며(적어도 ISO BMFF/MP4의 경우) 다른 솔루션도 개발 중입니다.
관련 기술 1
미디어 소스 확장 프로그램(MSE)
HTMLMediaElement는 단순한 아름다움을 지닌 생물입니다.
src URL을 제공하기만 하면 미디어를 로드, 디코딩, 재생할 수 있습니다.
<video src='foo.webm'></video>
Media Source API는 JavaScript가 동영상의 '청크'에서 재생을 위한 스트림을 빌드할 수 있도록 허용하여 미디어 소스를 더 세부적으로 제어할 수 있는 HTMLMediaElement의 확장 프로그램입니다. 이를 통해 적응형 스트리밍 및 타임시프팅과 같은 기법을 사용할 수 있습니다.
MSE가 EME에 중요한 이유는 무엇인가요? 상업 콘텐츠 제공업체는 보호된 콘텐츠를 배포하는 것 외에도 콘텐츠 전송을 네트워크 상태 및 기타 요구사항에 맞게 조정할 수 있어야 합니다. 예를 들어 Netflix는 네트워크 조건이 변경됨에 따라 스트림 비트 전송률을 동적으로 변경합니다. EME는 src
속성을 통해 제공된 미디어와 마찬가지로 MSE 구현에서 제공하는 미디어 스트림의 재생과 함께 작동합니다.
서로 다른 비트 전송률로 인코딩된 미디어를 청크 처리하고 재생하는 방법 아래의 DASH 섹션을 참고하세요.
simpl.info/mse에서 MSE가 작동하는 모습을 확인할 수 있습니다. 이 예에서는 File API를 사용하여 WebM 동영상이 5개의 청크로 분할됩니다. 프로덕션 애플리케이션에서는 동영상 청크가 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);
}
};
HTML5 Rocks 도움말에서 MSE에 대해 자세히 알아보세요.
관련 기술 #2
HTTP 동적 적응형 스트리밍(DASH)
멀티디바이스, 멀티플랫폼, 모바일 등 어떤 이름을 사용하든 웹은 연결 상태가 변경될 수 있는 환경에서 경험되는 경우가 많습니다. 동적 적응형 전송은 멀티스크린 환경에서 대역폭 제약 조건과 가변성을 처리하는 데 매우 중요합니다.
DASH(MPEG-DASH)는 불안정한 환경에서 스트리밍과 오프라인 저장 모두를 위한 최적의 미디어 전송을 지원하도록 설계되었습니다. Apple의 HTTP 라이브 스트리밍(HLS) 및 Microsoft의 Smooth Streaming과 같이 유사한 작업을 하는 다른 기술도 있지만 DASH는 HTTP를 통한 적응형 비트 전송률 스트리밍의 유일한 방법으로, 개방형 표준을 기반으로 합니다. DASH는 이미 YouTube와 같은 사이트에서 사용되고 있습니다.
EME 및 MSE와 어떤 관련이 있나요? MSE 기반 DASH 구현은 기존 HTTP 인프라를 사용하여 매니페스트를 파싱하고, 적절한 비트 전송률로 동영상 세그먼트를 다운로드하며, 동영상 요소에 피드할 수 있습니다.
즉, DASH를 사용하면 상업 콘텐츠 제공자가 보호된 콘텐츠를 적응형 스트리밍으로 수행할 수 있습니다.
DASH는 주석에 표시된 내용을 수행합니다.
- 동적: 변화하는 상황에 반응합니다.
- 적응형: 적절한 오디오 또는 동영상 비트 전송률을 제공하도록 조정됩니다.
- 스트리밍: 스트리밍뿐만 아니라 다운로드도 지원합니다.
- HTTP: 기존 스트리밍 서버의 단점 없이 HTTP의 이점을 활용하여 콘텐츠를 전송할 수 있습니다.
BBC는 DASH를 사용하여 테스트 스트림을 제공하기 시작했습니다.
요약
- 미디어는 다양한 비트 전송률로 인코딩됩니다.
- 다양한 비트 전송률 파일은 HTTP 서버에서 사용할 수 있습니다.
- 클라이언트 웹 앱은 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 지원을 맡기기로 했습니다. JavaScript로 DASH를 구현하면 브라우저를 업데이트하지 않고도 적응 알고리즘을 발전시킬 수 있습니다. 또한 MSE를 사용하면 브라우저를 변경하지 않고도 대체 매니페스트 형식과 전송 메커니즘을 실험할 수 있습니다. Google의 Shaka Player는 EME 지원 DASH 클라이언트를 구현합니다.
WebM 도구와 FFmpeg를 사용하여 동영상을 분할하고 MPD를 빌드하는 방법에 관한 안내는 Mozilla Developer Network를 참고하세요.
결론
웹을 통한 유료 동영상 및 오디오 전송이 엄청난 속도로 증가하고 있습니다. 태블릿, 게임 콘솔, 커넥티드 TV 또는 셋톱 박스와 같은 모든 새 기기는 HTTP를 통해 주요 콘텐츠 제공업체의 미디어를 스트리밍할 수 있습니다. 현재 85% 이상의 모바일 및 데스크톱 브라우저에서 <video>
및 <audio>
를 지원하며, Cisco는 2017년까지 동영상이 전 세계 소비자 인터넷 트래픽의 80~90%를 차지할 것으로 추정하고 있습니다. 이와 같은 맥락에서 브라우저 공급업체가 대부분의 미디어 플러그인이 사용하는 API에 대한 지원을 축소함에 따라 보호된 콘텐츠 배포를 위한 브라우저 지원이 점점 더 중요해질 수 있습니다.
추가 자료
사양 및 표준
- EME 사양: 최신 편집자 초안<
- 공통 암호화(CENC)
- 미디어 소스 확장 프로그램
- DASH 표준(PDF)
- DASH 표준 정보
기사
- DTG 웹 세미나(부분적으로 사용하지 않음)
- EME란 무엇인가요?, 헨리 시보넨 작성
- HTML5 Rocks 미디어 소스 확장 프로그램 도움말
- MPEG-DASH 테스트 스트림: BBC R&D 블로그 게시물