הגדרת IMA SDK ל-DAI

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

בחירת פתרון DAI שמעניין אתכם

הצגת DAI ב-Pod

במדריך הזה מוסבר איך להפעיל סטרימינג של פודים של DAI לתוכן בשידור חי או לתוכן על פי דרישה (VOD), באמצעות IMA DAI SDK ל-HTML5 עם נגן וידאו שמסתמך על hls.js להפעלה. כדי לראות או לעקוב אחרי שילוב לדוגמה שהושלם, עם תמיכה ב-HLS.js ובהפעלה ב-Safari, אפשר לעיין בדוגמה להצגת פודים ב-HLS. למידע על תמיכה ב-DASH.js, אפשר לעיין בדוגמה להצגת מודעות ב-DASH Pod. אפשר להוריד את האפליקציות לדוגמה האלה מדף הגרסה של HTML5 DAI ב-GitHub.

סקירה כללית על הצגת מודעות דינמיות (DAI) בבלוקים

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

  • PodStreamRequest / ‫PodVodStreamRequest: אובייקט שמגדיר בקשת סטרימינג לשרתי הפרסום של Google. בבקשות צריך לציין קוד רשת, וב-PodStreamRequest צריך לציין גם מפתח נכס בהתאמה אישית ומפתח API אופציונלי. שניהם כוללים פרמטרים אופציונליים נוספים.

  • StreamManager: אובייקט שמטפל בתקשורת בין סטרימינג הווידאו לבין IMA DAI SDK, כמו הפעלת פינגים למעקב והעברת אירועים של סטרימינג לבעל האפליקציה.

דרישות מוקדמות

לפני שמתחילים, צריך:

  • שלושה קבצים ריקים:

    • dai.html
    • dai.css
    • dai.js
  • ‫Python מותקן במחשב, או שרת אינטרנט או סביבת פיתוח אחרת באירוח לשימוש לבדיקה

הגדרת סביבת פיתוח

ה-SDK טוען תלות באמצעות אותו פרוטוקול כמו הדף שממנו הוא נטען, ולכן צריך להשתמש בשרת אינטרנט כדי לבדוק את האפליקציה. דרך מהירה להפעיל שרת פיתוח מקומי היא להשתמש בשרת המובנה של Python.

  1. משתמשים בשורת פקודה, מהספרייה שמכילה את הקובץ index.html, ומריצים את הפקודה:

    python -m http.server 8000
  2. בדפדפן אינטרנט, עוברים אל http://localhost:8000/

    אפשר גם להשתמש בכל סביבת פיתוח או שרת אינטרנט אחרים, כמו Apache HTTP Server.

יצירת נגן וידאו

קודם כל, משנים את dai.html כדי ליצור רכיב וידאו HTML5 ורכיב div לשימוש ברכיבי ממשק משתמש של מודעות. צריך גם להוסיף את התגים הנדרשים לטעינת הקבצים dai.css ו-dai.js, וגם לייבא את נגן הווידאו hls.js.

לאחר מכן, משנים את dai.css כדי לציין את הגודל והמיקום של רכיבי הדף. לבסוף, בקובץ dai.js, מגדירים משתנים שיכילו את פרטי בקשת הסטרימינג ואת הפונקציה initPlayer() שתופעל כשהדף ייטען.

אלה הקבועים של בקשת השידור:

  • BACKUP_STREAM: כתובת URL של שידור גיבוי שיופעל אם יתרחש שגיאה קריטית בתהליך הצגת המודעות.

  • STREAM_URL: משמש רק לשידורים חיים. כתובת ה-URL של שידור הווידאו שסופקה על ידי הכלי לשינוי מניפסטים או שותף צד שלישי באמצעות Pod Serving. הוא צריך לדרוש ממך להוסיף את מזהה הסטרימינג שסופק על ידי IMA DAI SDK, לפני שאתה שולח בקשה. במקרה הזה, כתובת ה-URL של הסטרימינג כוללת placeholder,‏ [[STREAMID]], שמוחלף במזהה הסטרימינג לפני שליחת הבקשה.

  • NETWORK_CODE: קוד הרשת של חשבון Ad Manager 360.

  • CUSTOM_ASSET_KEY: משמש רק לשידורים חיים. המפתח של נכס בהתאמה אישית שמזהה את אירוע הצגת המודעות ב-Ad Manager 360. אפשר ליצור אותו באמצעות הכלי לשינוי קובץ המניפסט או באמצעות שותף צד שלישי להצגת מודעות ב-Pod.

  • API_KEY: משמש רק לשידורים חיים. מפתח API אופציונלי, שיכול להיות נדרש כדי לאחזר מזהה של סטרימינג מ-IMA DAI SDK.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
  <h2>IMA DAI SDK Demo (HLS.JS)</h2>
    <video id="video"></video>
    <div id="adUi"></div>
</body>
</html>

dai.css

#video,
#adUi {
  width: 640px;
  height: 360px;
  position: absolute;
  top: 35px;
  left: 0;
}

#adUi {
  cursor: pointer;
}

dai.js

var BACKUP_STREAM =
    'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'

// Stream Config.
const STREAM_URL = "";
const NETWORK_CODE = "";
const CUSTOM_ASSET_KEY = "";
const API_KEY = "";

var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
}

טעינה של IMA DAI SDK

לאחר מכן, מוסיפים את מסגרת ה-DAI באמצעות תג סקריפט ב-dai.html, לפני התג של dai.js.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
...

מפעילים את StreamManager ושולחים בקשה לשידור חי או לסטרימינג של תוכן על פי דרישה (VOD)

הצגת פודקאסטים בשידור חי

כדי לבקש קבוצה של מודעות, צריך ליצור ima.dai.api.StreamManager, שאחראי לבקשת סטרימינג של DAI ולניהול שלו. הבנאי מקבל אלמנט וידאו, והמופע שמתקבל מקבל אלמנט בממשק המשתמש של המודעה כדי לטפל באינטראקציות עם המודעה.

לאחר מכן, מגדירים פונקציה כדי לבקש את השידור החי של הפוד. הפונקציה הזו יוצרת קודם PodStreamRequest, מגדירה אותו באמצעות הפרמטרים של streamRequest שסופקו בשלב 2, ואז קוראת ל-streamManager.requestStream() עם אובייקט הבקשה הזה.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestLivePodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}

function requestLivePodStream(networkCode, customAssetKey, apiKey) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving live Stream Request
  const streamRequest = new google.ima.dai.api.PodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.customAssetKey = customAssetKey;
  streamRequest.apiKey = apiKey;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

הצגת מודעות ב-VOD

כדי לבקש קבוצה של מודעות, צריך ליצור ima.dai.api.StreamManager, שאחראי לבקשת סטרימינג של DAI ולניהול שלו. הבנאי מקבל אלמנט וידאו, והמופע שמתקבל מקבל אלמנט בממשק המשתמש של המודעה כדי לטפל באינטראקציות עם המודעה.

לאחר מכן, מגדירים פונקציה לשליחת בקשה לשידור VOD של Pod Serving. הפונקציה הזו יוצרת קודם PodVodStreamRequest, מגדירה אותו באמצעות הפרמטרים של streamRequest שסופקו בשלב 2, ואז קוראת ל-streamManager.requestStream() עם אובייקט הבקשה הזה.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestVodPodStream(NETWORK_CODE);
}

function requestVodPodStream(networkCode) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving VOD Stream Request
  const streamRequest = new google.ima.dai.api.PodVodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

טיפול באירועים של שידור

הצגת פודקאסטים בשידור חי

לאחר מכן, מטמיעים מאזינים לאירועים (event listeners) לאירועים מרכזיים בסרטון. בדוגמה הזו, האירועים STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED ו-AD_BREAK_ENDED מטופלים על ידי קריאה לפונקציה onStreamEvent(). הפונקציה הזו מטפלת בטעינת הסטרימינג ובשגיאות, וגם בהשבתת אמצעי הבקרה של הנגן בזמן שמודעה מוצגת, כפי שנדרש על ידי ה-SDK. כשהשידור נטען, נטען נגן הווידאו ומופעלת כתובת ה-URL שצוינה באמצעות פונקציה loadStream().

dai.js

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      console.log('Stream initialized');
      loadStream(e.getStreamData().streamId);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream('');
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(streamID) {
  var url;
  if(streamID) {
    url = STREAM_URL.replace('[[STREAMID]]', streamID);
  } else {
    console.log('Stream Initialization Failed');
    url = BACKUP_STREAM;
  }
  console.log('Loading:' + url);
  hls.loadSource(url);
  hls.attachMedia(videoElement);
}

הצגת מודעות ב-VOD

לאחר מכן, מטמיעים מאזינים לאירועים (event listeners) לאירועים מרכזיים בסרטון. בדוגמה הזו מטפלים באירועים STREAM_INITIALIZED, LOADED, ERROR, AD_BREAK_STARTED ו-AD_BREAK_ENDED על ידי קריאה לפונקציה onStreamEvent(). הפונקציה הזו מטפלת בטעינת הסטרימינג ובשגיאות, וגם בהשבתת אמצעי הבקרה של הנגן בזמן שהמודעה מוצגת, כפי שנדרש על ידי ה-SDK.

בנוסף, בסטרימינג של מודעות ב-VOD Pod Serving צריך להפעיל את הפונקציה StreamManager.loadStreamMetadata() בתגובה לאירוע STREAM_INITIALIZED. בנוסף, צריך לבקש כתובת URL של סטרימינג משותף טכנולוגיית הווידאו (VTP). אחרי שהשיחה loadStreamMetadata() מצליחה, מופעל אירוע LOADED. בשלב הזה צריך להפעיל פונקציה loadStream() עם כתובת ה-URL של הסטרימינג כדי לטעון את הסטרימינג ולהפעיל אותו.

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      const streamId = e.getStreamData().streamId;
      // 'vtpInterface' is a place holder for your own video technology
      //  partner (VTP) API calls.
      vtpInterface.requestStreamURL({
        'streamId': streamId,
      })
      .then( (vtpStreamUrl) => {
        streamUrl = vtpStreamUrl;
        streamManager.loadStreamMetadata();
      }, (error) => {
        // Handle the error.
      });
      break;
    case google.ima.dai.api.StreamEvent.Type.LOADED:
      loadStream(streamUrl);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream();
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(url) {
  if(url) {
    console.log('Loading:' + url);
    hls.loadSource(url);
  } else {
    console.log('Stream Initialization Failed');
    hls.loadSource(BACKUP_STREAM);
  }
  hls.attachMedia(videoElement);
}

טיפול במטא-נתונים של שידורים חיים

בשלב הזה מטמיעים event listeners למטא-נתונים כדי להודיע ל-SDK כשמתרחשים אירועים שקשורים למודעות. האופן שבו מאזינים לאירועי מטא-נתונים בסטרימינג משתנה בהתאם לפורמט הסטרימינג (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);
       }
}

טיפול באירועי שחקנים

מוסיפים פונקציות event listener לאירועים pause ו-start של רכיב הווידאו כדי לאפשר למשתמש להמשיך בהפעלה כשה-SDK משהה את ההפעלה במהלך הפסקות הפרסום.

function loadStream(streamUrl) {
  ...
  
  videoElement.addEventListener('pause', onStreamPause);
  videoElement.addEventListener('play', onStreamPlay);
}

function onStreamPause() {
  console.log('paused');
  if (isAdBreak) {
    videoElement.controls = true;
    adUiElement.style.display = 'none';
  }
}

function onStreamPlay() {
  console.log('played');
  if (isAdBreak) {
    videoElement.controls = false;
    adUiElement.style.display = 'block';
  }
}

מחיקה של נכסי IMA DAI

אחרי שמסיימים בהצלחה את הבקשה וההצגה של מודעות בסטרימינג של Pod Serving באמצעות IMA DAI SDK, מומלץ לנקות את כל המשאבים אחרי שמסיימים את הסשן של Pod Serving. מתקשרים אל StreamManager.destroy() כדי להפסיק את ההפעלה של הסטרימינג, להפסיק את כל המעקב אחר מודעות ולבטל את כל נכסי הסטרימינג שנטענו.

כדי לקבל מידע על תכונות מתקדמות נוספות של SDK, אפשר לעיין במדריכים האחרים או בדוגמאות ב-GitHub.