טיפול במטא-נתונים מתוזמנים בשידורים לינאריים של הטמעת מודעות דינמיות (DAI)

ה-SDK של מודעות מדיה אינטראקטיביות (IMA) מסתמך על פרטי מטא-נתונים שמוטמעים בפלחי המדיה של השידור (מטא-נתונים בתוך הרצועה), או בקובץ המניפסט של הסטרימינג (מטא-נתונים במניפסט) כדי לעקוב אחר מיקומי הצופים ואירועי מודעות בצד הלקוח. המטא-נתונים נשלחים בפורמטים שונים, בהתאם לסוג השידור שמופעל.

נגן הווידאו מקבל באצוות מטא-נתונים מתוזמנים. בהתאם לנגן, אפשר להציג מטא-נתונים במועד שנקבע, או בקבוצות. לכל מחרוזת של מטא-נתונים משויכת חותמת זמן של הצגת (PTS) למועד שבו צריך להפעיל אותה.

האפליקציה שלך אחראית לתיעוד ולהעברה של המטא-נתונים אל IMA DAI SDK. ה-SDK מציע את השיטות הבאות להעברת המידע הזה:

onTimedMetadata

השיטה הזו מעבירה ל-SDK מחרוזות מטא-נתונים שמוכנות לעיבוד. נדרש ארגומנט אחד:

  • metadata: אובייקט שמכיל את המפתח TXXX עם ערך מחרוזת משויך שמתחיל ב-google_.
processMetadata

השיטה הזו מתזמנת מחרוזות מטא-נתונים לעיבוד של ה-SDK אחרי ה-PTS שצוין. הפונקציה משתמשת בארגומנטים הבאים:

  • type: מחרוזת שמכילה את סוג האירוע שעובר עיבוד. הערכים הקבילים הם ID3 ל-HLS או ל-urn:google:dai:2018 ל-DASH
  • data: ערך מחרוזת עם קידומת google_ או מערך בייטים שמפענח למחרוזת כזו.
  • timestamp: חותמת הזמן בשניות, שבה צריך לעבד את הנתונים.

כל סוג של מקור נתונים שנתמך על ידי IMA DAI SDK משתמש בצורה ייחודית של מטא-נתונים מתוזמנים, כפי שמתואר בקטעים הבאים.

שידורי HLS MPEG2TS

שידורי DAI HLS לינאריים שמשתמשים בקטעי MPEG2TS מעבירים מטא-נתונים מתוזמנים לנגן הווידאו באמצעות תגי ID3 מסוג in-band. תגי ה-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 מזהה3 מכיל PTS ביחס לאי ההמשכיות האחרונה בשידור.

החל מגרסה 1.2.0 של HLS.js, שני השחקנים המוצעים שלנו מעבירים למשתמש את ID3 דרך CMAF כאילו הם תגי ID3. לכן, הדוגמאות הבאות זהות לאלה של שידורי HLS MPEG2TS. עם זאת, יכול להיות שזה לא יהיה המצב אצל כל השחקנים, ולכן ייתכן שכדי לנתח את ID3 דרך eMSG כדי להטמיע תמיכה בשידורי CMAF ב-HLS יהיה צורך בקוד ייחודי.

הפעלה ב-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 כאירועים מסוג pseudo 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

שידורי DASH לינאריים של DAI מעבירים מטא-נתונים כאירועי מניפסט בזרם של אירועים, עם הערך schemeIdUri המותאם אישית urn:google:dai:2018. כל אירוע בשידורים האלה מכיל מטען ייעודי (payload) של טקסט ואת ה-PTS.

DASH.js

Dash.js מספק גורמים מטפלים באירועים בהתאמה אישית שנקראים על שם ערך schemeIdUri של כל מקור נתונים של אירועים. רכיבי ה-handler המותאמים אישית האלה מופעלים באצוות, כך שאתם צריכים לעבד את ערך ה-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

Shaka Player מציג אירועים כחלק מהאירוע timelineregionenter. בגלל חוסר תאימות בפורמט של Shaka Player, צריך לאחזר את ערך המטא-נתונים הגולמי דרך מאפיין הפרטים eventElement.attributes['messageData'].value.

לדוגמה:

player.addEventListener('timelineregionenter', function(event) {
  const detail = event.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;
    streamManager.processMetadata("urn:google:dai:2018", mediaId, pts);
  }
});
...

הגשה של קפסולות

בהצגת מטא-נתונים מתוזמנים, יש הגדרות שונות להעברת מטא-נתונים מתוזמנים, בהתאם לקריטריונים הבאים:

  • סוג השידור החי או ה-VOD
  • פורמט זרם HLS או DASH
  • סוג הנגן שבו נעשה שימוש
  • סוג הקצה העורפי של 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().

כדי להציג את פקדי הסרטונים באופן אוטומטי אחרי שהכול נטען ומוכן, מאזינים לאירוע DASH.js MANIFEST_LOADED.

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 עם שידורים חיים (פורמט זרמי DASH)

אם אתם משתמשים בנגן Shaka להפעלה של שידור חי, השתמשו במחרוזת '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 עם שידורי VOD (פורמט זרמי DASH)

אם אתם משתמשים בנגן Shaka להפעלה של שידור VOD, השתמשו במחרוזת '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);
       }
}