ערכות IMA SDK מאפשרות לשלב בקלות מודעות מולטימדיה באתרים ובאפליקציות. IMA SDK יכול לשלוח בקשות להצגת מודעות מכל שרת מודעות שתואם ל-VAST ולנהל את הפעלת המודעות באפליקציות שלכם. באמצעות ערכות IMA DAI SDK, האפליקציות שולחות בקשה לשידור של מודעות ותוכן וידאו – תוכן VOD או תוכן בשידור חי. לאחר מכן, ה-SDK מחזיר זרם וידאו משולב, כך שלא צריך לנהל את המעבר בין מודעה לתוכן וידאו באפליקציה.
בחירת פתרון DAI שמעניין אתכם
הצגת מודעות דינמיות (DAI) בפודקאסטים
במדריך הזה נדגים איך להפעיל סטרימינג של מודעות דינמיות (DAI) בפורמט Pod Serving לתוכן בשידור חי או לתוכן לפי דרישה (VOD), באמצעות IMA DAI SDK ל-HTML5 עם נגן וידאו שמסתמך על hls.js להפעלה. כדי לראות או לעקוב אחרי שילוב לדוגמה שהושלם, עם תמיכה ב-HLS.js וב-Safari Playback, אפשר לעיין בדוגמה להצגת פודקאסטים ב-HLS. למידע על תמיכה ב-DASH.js, אפשר לעיין בדוגמה של DASH Pod Serving. אפשר להוריד את האפליקציות לדוגמה האלה מדף הפרסום של 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.
משורת הפקודה, מהספרייה שמכילה את הקובץ
index.html, מריצים את הפקודה:python -m http.server 8000בדפדפן אינטרנט, עוברים אל
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 של שידור הווידאו שסופקה על ידי הכלי לשינוי מניפסט או שותף צד שלישי שמשתמש בהצגת מודעות בבלוקים. הוא צריך לדרוש ממך להוסיף את מזהה הסטרימינג שסופק על ידי IMA DAI SDK, לפני שאתה שולח בקשה. במקרה הזה, כתובת ה-URL של שידור כוללת placeholder,[[STREAMID]], שמוחלף במזהה הסטרימינג לפני שליחת הבקשה.
NETWORK_CODE: הקוד של הרשת של חשבון Ad Manager 360.
CUSTOM_ASSET_KEY: משמש רק לשידורים חיים. המפתח של נכס בהתאמה אישית שמזהה את אירוע הצגת המודעות בבלוק ב-Ad Manager 360. אפשר ליצור את הקובץ הזה באמצעות הכלי לשינוי קובץ המניפסט או באמצעות שותף צד שלישי שמספק פודים.
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 ושולחים בקשה לשידור חי או לשידור על פי דרישה
הצגת מודעות בשידור חי
כדי לבקש קבוצה של מודעות, צריך ליצור ima.dai.api.StreamManager, שאחראי לבקשת סטרימינג של DAI ולניהול שלו. הבונה מקבל אלמנט וידאו, והמופע שמתקבל מקבל רכיב בממשק המשתמש של מודעה כדי לטפל באינטראקציות עם המודעה.
לאחר מכן, מגדירים פונקציה לשליחת בקשה לשידור חי של Pod Serving. הפונקציה הזו יוצרת קודם אובייקט 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 של הפוד. הפונקציה הזו יוצרת קודם אובייקט 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), לסוג הסטרימינג (שידור חי או סטרימינג של VOD), לסוג הנגן ולסוג ה-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 להפעלה של סטרימינג של 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);
}
}
טיפול בפעולות במשחק
מוסיפים פונקציות 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.