Encrypted Media Extensions (EME) מספק ממשק API שמאפשר לאפליקציות אינטרנט לקיים אינטראקציה עם מערכות להגנה על תוכן, כדי לאפשר הפעלה של אודיו וידאו מוצפנים.
EME נועד לאפשר שימוש באותה אפליקציה ובקבצים מוצפנים בכל דפדפן, ללא קשר למערכת ההגנה הבסיסית. האפשרות הראשונה מתאפשרת באמצעות ממשקי ה-API והתהליך הסטנדרטיים, והאפשרות השנייה מתאפשרת באמצעות הרעיון של הצפנה משותפת.
EME הוא תוסף למפרט HTMLMediaElement
– ומכאן השם. העובדה ש-EME הוא 'תוסף' מאפשרת לדפדפנים לבחור אם לתמוך בו: אם דפדפן לא תומך במדיה מוצפנת, הוא לא יוכל להפעיל מדיה מוצפנת, אבל EME לא נדרש כדי לעמוד בדרישות של מפרט HTML. ממפרט ה-EME:
הטמעות של EME משתמשות ברכיבים החיצוניים הבאים:
- מערכת מפתחות: מנגנון להגנה על תוכן (DRM). EME לא מגדיר מערכות מפתחות בעצמו, מלבד Clear Key (מידע נוסף מופיע בהמשך).
- מודול לפענוח תוכן (CDM): מנגנון תוכנה או חומרה בצד הלקוח שמאפשר הפעלה של מדיה מוצפנת. בדומה ל-Key Systems, EME לא מגדיר מערכות CDM, אלא מספק ממשק לאפליקציות כדי שיוכלו לקיים אינטראקציה עם מערכות CDM זמינות.
- שרת רישיונות (מפתחות): מתקשר עם CDM כדי לספק מפתחות לפענוח מדיה. המשא ומתן עם שרת הרישיונות הוא באחריות האפליקציה.
- שירות אריזה: קידוד והצפנה של מדיה לצורכי הפצה או שימוש.
חשוב לזכור שאפליקציה שמשתמשת ב-EME יוצרת אינטראקציה עם שרת רישיונות כדי לקבל מפתחות שמאפשרים פענוח, אבל הזהות והאימות של המשתמש לא נכללים ב-EME. אחזור המפתחות כדי לאפשר הפעלת מדיה מתבצע אחרי אימות המשתמש (אופציונלי). שירותים כמו Netflix חייבים לאמת משתמשים באפליקציית האינטרנט שלהם: כשמשתמש נכנס לאפליקציה, האפליקציה קובעת את הזהות וההרשאות של המשתמש.
איך פועל EME?
כך מתבצעת האינטראקציה בין הרכיבים של EME, בהתאם לדוגמת הקוד הבאה:
- אפליקציית אינטרנט מנסה להפעיל אודיו או וידאו עם שידור מוצפן אחד או יותר.
- הדפדפן מזהה שהמדיה מוצפנת (בתיבת הסבר למטה מראה איך זה קורה) ומפעיל אירוע
encrypted
עם מטא-נתונים (initData
) שהתקבלו מהמדיה לגבי ההצפנה. - האפליקציה מטפלת באירוע
encrypted
:- אם לא שויך לאלמנט המדיה אובייקט
MediaKeys
, קודם צריך לבחור מערכת מפתחות זמינה באמצעותnavigator.requestMediaKeySystemAccess()
כדי לבדוק אילו מערכות מפתחות זמינות, ואז ליצור אובייקטMediaKeys
למערכת מפתחות זמינה באמצעות אובייקטMediaKeySystemAccess
. חשוב לזכור שהפעלת האובייקט MediaKeys צריכה להתרחש לפני האירועencrypted
הראשון. האפליקציה מקבלת את כתובת ה-URL של שרת הרישיון בנפרד מהבחירה במערכת מפתחות זמינה. אובייקטMediaKeys
מייצג את כל המפתחות שזמינים לפענוח המדיה של רכיב אודיו או וידאו. הוא מייצג מכונה של CDM ומספק גישה ל-CDM, במיוחד ליצירת סשנים של מפתחות, המשמשים לקבלת מפתחות משרת רישיונות. - אחרי שיוצרים את האובייקט
MediaKeys
, מקצים אותו לרכיב המדיה:setMediaKeys()
משיייך את האובייקטMediaKeys
ל-HTMLMediaElement, כדי שאפשר יהיה להשתמש במפתחות שלו במהלך ההפעלה, כלומר במהלך פענוח הנתונים.
- אם לא שויך לאלמנט המדיה אובייקט
- האפליקציה יוצרת
MediaKeySession
על ידי קריאה ל-createSession()
ב-MediaKeys
. הפונקציה יוצרתMediaKeySession
שמייצג את משך החיים של רישיון והמפתחות שלו. - האפליקציה יוצרת בקשת רישיון על ידי העברת נתוני המדיה שהתקבלו במטפל
encrypted
ל-CDM, באמצעות קריאה ל-generateRequest()
ב-MediaKeySession
. - ה-CDM יוצר אירוע
message
: בקשה לקבלת מפתח משרת רישיונות. - האובייקט
MediaKeySession
מקבל את האירועmessage
והאפליקציה שולחת הודעה לשרת הרישיונות (לדוגמה, באמצעות XHR). - האפליקציה מקבלת תשובה משרת הרישיונות ומעבירה את הנתונים ל-CDM באמצעות השיטה
update()
שלMediaKeySession
. - ה-CDM מפענח את המדיה באמצעות המפתחות ברישיון. אפשר להשתמש במפתח תקף מכל סשן בתוך הערכים של
MediaKey
שמשויכים לרכיב המדיה. ה-CDM ייגש למפתח ולמדיניות, וייוצרו להם אינדקסים לפי מזהה המפתח. - הפעלת המדיה תמשיך.
אוף…
שימו לב: יכולות להיות כמה הודעות בין ה-CDM לבין שרת הרישיונות, וכל התקשורת בתהליך הזה היא אטומה לדפדפן ולאפליקציה: רק ה-CDM ושרת הרישיונות מבינים את ההודעות, אבל שכבת האפליקציה יכולה לראות איזה סוג הודעה ה-CDM שולח. בקשת הרישיון מכילה הוכחה לתקינות של CDM (וליחסי האמון שלו), וגם מפתח לשימוש בהצפנת מפתחות התוכן ברישיון שנוצר.
…אבל מה CDMs עושים בפועל?
הטמעת EME לא מספקת בעצמה דרך לפענח מדיה: היא פשוט מספקת ממשק API לאפליקציית אינטרנט כדי ליצור אינטראקציה עם מודולים לפענוח תוכן.
הפעילות בפועל של CDM לא מוגדרת במפרט EME, ו-CDM יכול לטפל גם בפענוח (דחיסה) של מדיה וגם בפענוח. יש כמה אפשרויות פוטנציאליות לפונקציונליות של CDM, מהחלשה ביותר ועד החזקה ביותר:
- פענוח בלבד, שמאפשר הפעלה באמצעות צינור עיבוד הנתונים הרגיל של המדיה, למשל באמצעות רכיב
<video>
. - פענוח ופענוח, העברת פריטי וידאו לדפדפן לצורך עיבוד.
- פענוח ופענוח, עיבוד ישירות בחומרה (לדוגמה, ה-GPU).
יש כמה דרכים להפוך מאגר נתונים מנוהל (CDM) לזמין לאפליקציית אינטרנט:
- חבילה של CDM עם הדפדפן.
- הפצת CDM בנפרד.
- פיתוח CDM במערכת ההפעלה.
- הוספת CDM לקושחה.
- הטמעת CDM בחומרה.
אופן הזמינות של CDM לא מוגדר במפרט EME, אבל בכל המקרים הדפדפן אחראי על בדיקת ה-CDM ועל חשיפת ה-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')
);
}
הצפנה משותפת
פתרונות של הצפנה משותפת מאפשרים לספקים של תוכן להצפין ולארז את התוכן שלהם פעם אחת לכל מאגר/קודק, ולהשתמש בו עם מגוון מערכות מפתחות, פלטפורמות ניהול נתונים וסוכני לקוח: כלומר, כל פלטפורמת ניהול נתונים שתומכת בהצפנה משותפת. לדוגמה, אפשר להפעיל סרטון שארוז באמצעות PlayReady בדפדפן באמצעות CDM של Widevine שמקבל מפתח משרת רישיונות של Widevine.
בניגוד לפתרונות מדור קודם, שפועלים רק עם סטאק אנכי מלא, כולל לקוח יחיד שלרוב כולל גם סביבת זמן ריצה של אפליקציה.
הצפנה משותפת (CENC) היא תקן ISO שמגדיר סכימה להגנה על ISO BMFF. רעיון דומה חל על WebM.
מקש ניקוי
אמנם EME לא מגדיר את הפונקציונליות של DRM, אבל לפי המפרט הנוכחי, כל הדפדפנים שתומכים ב-EME חייבים להטמיע את Clear Key. באמצעות המערכת הזו, אפשר להצפין מדיה באמצעות מפתח ולאחר מכן להפעיל אותה פשוט על ידי מתן המפתח. אפשר להטמיע את Clear Key בדפדפן: הוא לא מחייב שימוש במודול נפרד לפענוח.
סביר להניח שלא ייעשה שימוש ב-Clear Key בסוגים רבים של תוכן מסחרי, אבל הוא תומך בכל הדפדפנים שתומכים ב-EME. הוא גם שימושי לבדיקת הטמעות של EME ואפליקציות שמשתמשות ב-EME, בלי צורך לבקש מפתח תוכן משרת רישיונות. דוגמה פשוטה ל-Clear Key זמינה בכתובת 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]
}));
}
כדי לבדוק את הקוד הזה, צריך להפעיל סרטון מוצפן. אפשר להצפין סרטון לשימוש עם Clear Key בפורמט WebM לפי ההוראות של webm_crypt. יש גם שירותים מסחריים (לפחות ל-ISO BMFF/MP4), ואנחנו מפתחים פתרונות נוספים.
טכנולוגיה קשורה מס' 1
תוספים של מקורות מדיה (MSE)
HTMLMediaElement הוא יצור פשוט ויפה.
אנחנו יכולים לטעון, לפענח ולהפעיל מדיה פשוט על ידי מתן כתובת URL של src:
<video src='foo.webm'></video>
Media Source API הוא תוסף ל-HTMLMediaElement שמאפשר שליטה פרטנית יותר על מקור המדיה, על ידי מתן אפשרות ל-JavaScript ליצור סטרימינג להפעלה מ 'קטעים' של וידאו. כך אפשר להשתמש בשיטות כמו סטרימינג אדפטיבי ושינוי מהירות.
למה MSE חשוב ל-EME? הסיבה לכך היא שבנוסף להפצת תוכן מוגן, ספקי תוכן מסחרי צריכים להיות מסוגלים להתאים את העברת התוכן לתנאי הרשת ולדרישות אחרות. לדוגמה, Netflix משנה באופן דינמי את קצב הנתונים של הסטרימינג בהתאם לשינויים בתנאי הרשת. EME פועל עם הפעלה של שידורי מדיה שסופקו על ידי הטמעת MSE, בדיוק כמו שהוא פועל עם מדיה שסופקה באמצעות מאפיין src
.
איך מחלקים קטעים של מדיה שקודדה בקצב העברת נתונים שונה ומפעילים אותם? עיינו בקטע DASH בהמשך.
אפשר לראות את MSE בפעולה בכתובת simpl.info/mse. לצורך הדוגמה הזו, סרטון WebM מחולק לחמישה קטעים באמצעות ממשקי ה-API של קבצים. באפליקציה בסביבת ייצור, קטעי וידאו יאוחזרו באמצעות 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);
}
};
מידע נוסף על MSE זמין במאמר HTML5 Rocks.
טכנולוגיה קשורה מס' 2
שידור דינמי שניתן להתאמה באמצעות HTTP (DASH)
מכשירים מרובים, פלטפורמות מרובות, מכשירים ניידים – לא משנה איך אתם קוראים לזה, בדרך כלל משתמשים באינטרנט בתנאים של קישוריות משתנה. העברה דינמית ומותאמת היא קריטית כדי להתמודד עם מגבלות רוחב פס ועם התנודות בעולם של מכשירים מרובים.
DASH (נקרא גם MPEG-DASH) נועד לספק את העברת המדיה הטובה ביותר האפשרית בעולם לא יציב, גם בסטרימינג וגם בהורדה. יש כמה טכנולוגיות אחרות שמבצעות פעולה דומה – כמו HTTP Live Streaming (HLS) של Apple ו-Smooth Streaming של Microsoft – אבל DASH היא השיטה היחידה לשידור דינמי של קצב נתונים מותאם באמצעות HTTP שמבוססת על תקן פתוח. אתרים כמו YouTube כבר משתמשים ב-DASH.
מה הקשר ל-EME ול-MSE? הטמעות DASH שמבוססות על MSE יכולות לנתח מניפסט, להוריד קטעי וידאו בקצב נתונים מתאים ולהעביר אותם לרכיב וידאו כשהוא זקוק לנתונים – באמצעות תשתית HTTP קיימת.
במילים אחרות, DASH מאפשר לספקים של תוכן מסחרי לבצע סטרימינג אדפטיבי של תוכן מוגן.
ה-DASH עושה את מה שהוא מציע:
- דינמי: תגובה לתנאים משתנים.
- דינמי: הסרטון מותאם כדי לספק קצב דגימה מתאים של אודיו או וידאו.
- סטרימינג: מאפשר סטרימינג וגם הורדה.
- HTTP: מאפשר העברת תוכן עם היתרונות של HTTP, בלי החסרונות של שרת סטרימינג רגיל.
BBC התחילה לספק שידורי בדיקה באמצעות DASH:
לסיכום:
- המדיה מקודדת בקצב העברת נתונים שונה.
- קבצים עם שיעורי ביט שונים זמינים משרת HTTP.
- אפליקציית אינטרנט לקוח בוחרת את קצב הנתונים לאחזור ולהפעלה באמצעות DASH.
כחלק מתהליך פילוח הסרטון, מניפסט XML שנקרא תיאור של הצגת מדיה (MPD) נוצר באופן פרוגרמטי. כאן מתוארים קבוצות של התאמות ותצוגות, עם משכי זמן וכתובות 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 הזה נלקח מקובץ ה- .mpd שמשמש את נגן הדגמה של YouTube DASH)
לפי מפרט DASH, באופן תיאורטי אפשר להשתמש בקובץ MPD בתור src
של סרטון. עם זאת, כדי לתת גמישות רבה יותר למפתחי אתרים, יצרני הדפדפנים בחרו להשאיר את התמיכה ב-DASH לספריות JavaScript שמשתמשות ב-MSE, כמו dash.js. הטמעת DASH ב-JavaScript מאפשרת לאלגוריתם ההתאמה להתפתח בלי צורך בעדכוני דפדפן. השימוש ב-MSE מאפשר גם להתנסות בפורמטים חלופיים של מניפסט ובמנגנוני העברה בלי צורך בשינויים בדפדפן. Shaka Player של Google מטמיע לקוח DASH עם תמיכה ב-EME.
ב-Mozilla Developer Network יש הוראות לשימוש בכלים של WebM ו-FFmpeg כדי לפלח סרטונים וליצור קובץ MPD.
סיכום
השימוש באינטרנט להעברת סרטונים ואודיו בתשלום הולך וגדל בקצב עצום. נראה שכל מכשיר חדש, בין אם מדובר בטאבלט, בקונסולת משחקים, בטלוויזיה מחוברת או בממיר, מסוגל להעביר מדיה בסטרימינג מספקי התוכן הגדולים ביותר באמצעות HTTP. יותר מ-85% מהדפדפנים לנייד ולמחשב תומכים עכשיו ב-<video>
וב-<audio>
, וסיכום של Cisco הוא שסרטונים ייצגו 80 עד 90 אחוז מתנועת הגולשים הגלובלית באינטרנט עד שנת 2017. בהקשר הזה, סביר להניח שתמיכת הדפדפן בהפצת תוכן מוגן תהיה משמעותית יותר ויותר, כי ספקי הדפדפנים מקטיזים את התמיכה בממשקי ה-API שרוב יישומי הפלאגין של המדיה מסתמכים עליהם.
קריאה נוספת
מפרטים ותקנים
- מפרט EME: טיוטת העורכים האחרונה<
- הצפנה נפוצה (CENC)
- תוספי מקורות מדיה
- תקן DASH (כן, זה קובץ PDF)
- מידע על תקן DASH
מאמרים
- וובינר בנושא DTG (חלקית לא רלוונטי)
- מה זה EME?, מאת Henri Sivonen
- מאמר בנושא HTML5 Rocks Media Source Extensions
- נתוני זרם לבדיקה של MPEG-DASH: פוסט בבלוג של BBC R&D