ה-SDK של Interactive Media Ads (IMA) Dynamic Ad Insertion (DAI) (הטמעה דינמית של מודעות) מסתמך על מידע מטא-נתונים שמוטמע בפלחי המדיה של הסטרימינג (מטא-נתונים בתוך הסטרימינג) או בקובץ המניפסט של הסטרימינג (מטא-נתונים במניפסט) כדי לעקוב אחרי המיקום של הצופים ואירועי מודעות בצד הלקוח. המטא-נתונים נשלחים בפורמטים שונים, בהתאם לסוג הסטרימינג שמופעל.
נגן הווידאו מקבל מטא-נתונים עם חותמות זמן באצוות. בהתאם לנגן, המטא-נתונים יכולים להופיע בזמן המתוזמן או בקבוצות. לכל מחרוזת מטא-נתונים יש חותמת זמן (PTS) שמשויכת לה, שמציינת מתי צריך להפעיל אותה.
האפליקציה אחראית לתיעוד המטא-נתונים ולהעברתם אל IMA DAI SDK. ה-SDK מציע את השיטות הבאות להעברת המידע הזה:
- onTimedMetadata
השיטה הזו מעבירה מחרוזות של מטא-נתונים שמוכנות לעיבוד אל ה-SDK. היא מקבלת ארגומנט אחד:
-
metadata
: אובייקט שמכיל מפתח שלTXXX
עם ערך מחרוזת משויך שמתחיל ב-google_
.
-
- processMetadata
בשיטה הזו, מחרוזות המטא-נתונים מתוזמנות לעיבוד על ידי ה-SDK אחרי ה-PTS שצוין. הפונקציה מקבלת את הארגומנטים הבאים:
-
type
: מחרוזת שמכילה את סוג האירוע שעובר עיבוד. הערכים האפשריים הםID3
ל-HLS אוurn:google:dai:2018
ל-DASH -
data
: ערך מחרוזת עם הקידומתgoogle_
או מערך בייטים בפורמט הבא:ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx
. -
timestamp
: חותמת הזמן בשניות שבה הנתונים צריכים לעבור עיבוד.
-
כל סוג סטרימינג שנתמך על ידי IMA DAI SDK משתמש בצורה ייחודית של מטא-נתונים מתוזמנים, כפי שמתואר בקטעים הבאים.
שידורי HLS MPEG2TS
בסטרימינג לינארי של DAI בפורמט HLS, פלחים של MPEG2TS מעבירים מטא-נתונים מתוזמנים לנגן הווידאו באמצעות תגי ID3 בתוך הפס. תגי ID3 האלה מוטמעים בפלחי MPEG2TS ומקבלים את שם השדה TXXX (לתוכן טקסט מותאם אישית שהוגדר על ידי המשתמש).
הפעלה ב-Safari
דפדפן Safari מעבד תגי ID3 באופן אוטומטי, כרצועה מוסתרת, כך שאירועי cuechange מופעלים בזמן הנכון כדי לעבד כל חלק של מטא-נתונים. אפשר להעביר את כל המטא-נתונים אל IMA DAI SDK, בלי קשר לתוכן או לסוג. מטא-נתונים לא רלוונטיים מסוננים באופן אוטומטי.
לדוגמה:
videoElement.textTracks.addEventListener('addtrack', (e) => {
const track = e.track;
if (track.kind === 'metadata') {
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
for (const cue of track.activeCues) {
const metadata = {};
metadata[cue.value.key] = cue.value.data;
streamManager.onTimedMetadata(metadata);
}
});
}
});
...
HLS.js
HLS.js מספק תגי ID3 באצוות דרך האירוע FRAG_PARSING_METADATA
, כמערך של דוגמאות. HLS.js לא מתרגם את נתוני ה-ID3 ממערכי בייטים
למחרוזות ולא מבצע היסט לאירועים ל-PTS המתאים שלהם. אין צורך לפענח את נתוני הדוגמה ממערך בייטים למחרוזת, או לסנן תגי ID3 לא רלוונטיים, כי IMA DAI SDK מבצע את הפענוח והסינון האלה באופן אוטומטי.
לדוגמה:
hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
if (streamManager && data) {
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
});
...
שידורי HLS CMAF
בסטרימינג לינארי של DAI ב-HLS באמצעות Common Media Application Framework (CMAF), מטא-נתונים מתוזמנים מועברים דרך תיבות eMSGv1 בתוך פס התדרים בהתאם לתקן ID3 דרך CMAF. תיבות ה-eMSG האלה מוטמעות בתחילת כל פלח מדיה, וכל eMSG של ID3 מכיל PTS ביחס לאי הרציפות האחרונה בזרם.
החל מגרסה 1.2.0 של HLS.js, שני הנגנים המוצעים שלנו מעבירים ID3 דרך CMAF למשתמש כאילו מדובר בתגי ID3. לכן, הדוגמאות הבאות זהות לדוגמאות של זרמי HLS MPEG2TS. עם זאת, יכול להיות שזה לא המצב בכל הנגנים, ולכן כדי להטמיע תמיכה בסטרימינג של HLS CMAF, יכול להיות שיהיה צורך בקוד ייחודי לניתוח ID3 באמצעות eMSG.
הפעלה ב-Safari
דפדפן Safari מתייחס למטא-נתונים של ID3 באמצעות eMSG כאל אירועי ID3 פסאודו, ומספק אותם במנות, באופן אוטומטי, כאל טראק מוסתר, כך שאירועי cuechange מופעלים בזמן הנכון כדי לעבד כל חלק של המטא-נתונים. אפשר להעביר את כל המטא-נתונים אל IMA DAI SDK, גם אם הם לא רלוונטיים לתזמון. כל המטא-נתונים שלא קשורים ל-DAI מסוננים באופן אוטומטי.
לדוגמה:
videoElement.textTracks.addEventListener('addtrack', (e) => {
const track = e.track;
if (track.kind === 'metadata') {
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
for (const cue of track.activeCues) {
const metadata = {};
metadata[cue.value.key] = cue.value.data;
streamManager.onTimedMetadata(metadata);
}
});
}
});
...
HLS.js
החל מגרסה 1.2.0, HLS.js מתייחס למטא-נתונים של ID3 דרך eMSG כאל אירועי פסאודו ID3, ומספק אותם בקבוצות, דרך האירוע FRAG_PARSING_METADATA
, כמערך של דוגמאות. HLS.js לא מתרגם את נתוני ID3 ממערכי בייטים
למחרוזות, ולא מבצע היסט לאירועים ל-PTS המתאים שלהם. אין צורך לפענח את נתוני הדוגמה ממערך בייטים למחרוזת, כי IMA DAI SDK מבצע את הפענוח הזה באופן אוטומטי.
לדוגמה:
hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
if (streamManager && data) {
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
});
...
מקורות נתונים ב-DASH
בסטרימינג של DAI DASH לינארי, המטא-נתונים מועברים כאירועים של מניפסט בסטרימינג של אירועים עם הערך המותאם אישית schemeIdUri
urn:google:dai:2018
. כל אירוע בזרמים האלה מכיל מטען ייעודי (payload) של טקסט, ואת חותמת הזמן של האירוע.
DASH.js
Dash.js מספקת מטפלים באירועים מותאמים אישית שנקראים על שם הערך של schemeIdUri של כל זרם אירועים. הפונקציות האלה מופעלות בקבוצות, ולכן אתם צריכים לעבד את הערך של PTS כדי לתזמן את האירוע בצורה נכונה. IMA DAI SDK יכול לטפל בזה בשבילכם באמצעות השיטה streamManager, processMetadata()
.
לדוגמה:
const dash = dashjs.MediaPlayer().create();
dash.on('urn:google:dai:2018', (payload) => {
const mediaId = payload.event.messageData;
const pts = payload.event.calculatedPresentationTime;
streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
});
...
Shaka Player
Shaka Player מציג אירועים כחלק מהאירוע timelineregionenter
. בגלל חוסר תאימות לפורמט של Shaka Player, צריך לאחזר את ערך המטא-נתונים בצורה גולמית דרך מאפיין הפרטים eventNode.attributes['messageData']
.
לדוגמה:
player.addEventListener('timelineregionenter', function(event) {
const detail = event.detail;
if ( detail.eventNode.attributes &&
detail.eventNode.attributes['messageData']) {
const mediaId = detail.eventNode.attributes['messageData'];
const pts = detail.startTime;
streamManager.processMetadata("urn:google:dai:2018", mediaId, pts);
}
});
...
הצגת מודעות ב-Pod
בשידור של פודקאסטים, יש הגדרות שונות להעברת מטא-נתונים עם חותמת זמן, בהתאם לקריטריונים הבאים:
- סוג הסטרימינג: שידור חי או VOD
- פורמט שידור HLS או DASH
- סוג הנגן שבו נעשה שימוש
- סוג ה-backend של DAI שבו נעשה שימוש
פורמט שידור HLS (שידורים חיים ושידורי VOD, נגן HLS.js)
אם אתם משתמשים בנגן HLS.js, צריך להאזין לאירוע FRAG_PARSING_METADATA
של HLS.js כדי לקבל מטא נתונים של ID3 ולהעביר אותם אל ה-SDK באמצעות StreamManager.processMetadata()
.
כדי להפעיל את הסרטון באופן אוטומטי אחרי שכל הרכיבים נטענים ומוכנים, צריך להאזין לאירוע MANIFEST_PARSED
של HLS.js כדי להפעיל את ההפעלה.
function loadStream(streamID) {
hls.loadSource(url);
hls.attachMedia(videoElement);
// Timed metadata is passed HLS stream events to the streamManager.
hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
}
function parseID3Events(event, data) {
if (streamManager && data) {
// For each ID3 tag in the metadata, pass in the type - ID3, the
// tag data (a byte array), and the presentation timestamp (PTS).
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
}
function startPlayback() {
console.log('Video Play');
videoElement.play();
}
DASH.js (פורמט של שידורי DASH, סוג השידור: שידור חי ו-VOD)
אם אתם משתמשים בנגן DASH.js, אתם צריכים להשתמש במחרוזות שונות כדי להאזין למטא-נתוני ID3 לשידורים חיים או לסטרימינג של תוכן על פי דרישה (VOD):
- שידורים חיים:
'https://developer.apple.com/streaming/emsg-id3'
- שידורי VOD:
'urn:google:dai:2018'
מעבירים את המטא-נתונים של ID3 אל ה-SDK באמצעות StreamManager.processMetadata()
.
כדי להציג באופן אוטומטי את אמצעי הבקרה של הסרטון אחרי שכל הרכיבים נטענים ומוכנים, צריך להאזין לאירוע MANIFEST_LOADED
של DASH.js.
const googleLiveSchema = 'https://developer.apple.com/streaming/emsg-id3';
const googleVodSchema = 'urn:google:dai:2018';
dashPlayer.on(googleLiveSchema, processMetadata);
dashPlayer.on(googleVodSchema, processMetadata);
dashPlayer.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
function processMetadata(metadataEvent) {
const messageData = metadataEvent.event.messageData;
const timestamp = metadataEvent.event.calculatedPresentationTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with dash.js.
streamManager.processMetadata('ID3', messageData, timestamp);
}
function loadlistener() {
showControls();
// This listener must be removed, otherwise it triggers as addional
// manifests are loaded. The manifest is loaded once for the content,
// but additional manifests are loaded for upcoming ad breaks.
dashPlayer.off(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
}
Shaka Player עם שידורים חיים (פורמט שידורי DASH)
אם אתם משתמשים ב-Shaka player להפעלת שידורים חיים, צריך להשתמש במחרוזת 'emsg'
כדי להאזין לאירועי מטא-נתונים.
לאחר מכן, משתמשים בנתוני הודעת האירוע בקריאה אל StreamManager.onTimedMetadata()
.
shakaPlayer.addEventListener('emsg', (event) => onEmsgEvent(event));
function onEmsgEvent(metadataEvent) {
// Use StreamManager.onTimedMetadata() if your video player provides
// processed metadata, as with Shaka player livestreams.
streamManager.onTimedMetadata({'TXXX': metadataEvent.detail.messageData});
}
Shaka Player עם שידורי VOD (פורמט שידורי DASH)
אם אתם משתמשים ב-Shaka player להפעלה של סטרימינג של תוכן על פי דרישה, צריך להשתמש במחרוזת 'timelineregionenter'
כדי להאזין לאירועי מטא-נתונים. לאחר מכן, משתמשים בנתוני הודעת האירוע בקריאה אל
StreamManager.processMetadata()
עם המחרוזת 'urn:google:dai:2018'
.
shakaPlayer.addEventListener('timelineregionenter', (event) => onTimelineEvent(event));
function onTimelineEvent(metadataEvent) {
const detail = metadataEvent.detail;
if ( detail.eventElement.attributes &&
detail.eventElement.attributes['messageData'] &&
detail.eventElement.attributes['messageData'].value ) {
const mediaId = detail.eventElement.attributes['messageData'].value;
const pts = detail.startTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with Shaka player VOD streams.
streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
}
}