הגדרת IMA SDK ל-DAI

בחירת פלטפורמה: HTML5 Android iOS tvOS Cast Roku

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

הצגת מודעות דינמיות (DAI) בפודקאסטים

ערכות IMA SDK מפשטות את השילוב של מודעות מולטימדיה באתרים ובאפליקציות.

‫IMA SDK יכול לשלוח בקשות למודעות מכל שרת מודעות שתואם ל-VAST ולנהל את הפעלת המודעות באפליקציות.

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

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

לפני שמשתמשים במדריך הזה, כדאי להכיר את הפרוטוקול של Web Receiver ב-Chromecast Application Framework. המדריך הזה מיועד למי שיש לו הבנה בסיסית במושגים של מקלט CAF, כמו message interceptors ואובייקטים של mediaInformation, ושיודע להשתמש בכלי השליטה והבקרה של Cast כדי לבצע אמולציה של שולח CAF.

כדי להשתמש ב-Pod Serving ב-IMA DAI, צריך לעבוד עם שותף Pod Serving ולהיות בעלי חשבון Ad Manager 360 Advanced. אם יש לכם חשבון Ad Manager, אתם יכולים לפנות למנהל החשבון שלכם לקבלת פרטים נוספים. מידע על הרשמה ל-Ad Manager זמין במרכז העזרה של Ad Manager.

מידע על שילוב עם פלטפורמות אחרות או על שימוש ב-IMA SDKs בצד הלקוח מופיע במאמר Interactive Media Ads SDKs.

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

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

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

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

הגדרת אובייקטים של MediaInfo של השולח

קודם כול, מגדירים את אובייקט MediaInfo של אפליקציית השולח כך שיכלול את השדות הבאים:

שדה תוכן עניינים
contentId מזהה ייחודי של פריט המדיה.

CONTENT_ID

contentUrl אופציונלי. כתובת URL של שידור לגיבוי, להפעלה אם טעינת השידור עם DAI נכשלת.

BACKUP_STREAM_URL

contentType אופציונלי. סוג ה-MIME של מקורות נתוני הגיבוי של התוכן. המאפיין הזה נדרש רק לפידים של DASH.

CONTENT_STREAM_MIMETYPE

streamType המחרוזת המילולית או הקבוע שמשמשים לערך הזה משתנים בהתאם לפלטפורמה של השולח.
customData השדה customData מכיל מאגר של צמדי מפתח/ערך של שדות חובה נוספים. בדוגמה הזו, הוא מכיל את הפרמטרים של הזרם ב-DAI. באפליקציית ייצור, אפשר להעביר במקום זאת מזהה שאפליקציית מקלט Cast תשתמש בו כדי לאחזר את הפרמטרים האלה באמצעות בקשה בצד השרת.
שדה תוכן עניינים
daiStreamType סוג השידור של DAI. אחת מהאפשרויות הבאות: "LIVE" או "VOD"

DAI_STREAM_TYPE

networkCode הקוד של הרשת בחשבון Google Ad Manager 360.

NETWORK_CODE

customAssetKey השדה הזה נדרש רק לשידורים חיים. מפתח הנכס המותאם אישית שמזהה את אירוע הצגת רצף המודעות ב-Google Ad Manager 360.

CUSTOM_ASSET_KEY

apiKey מפתח API אופציונלי לאחזור מזהה של סטרימינג מ-IMA DAI SDK.

API_KEY

ריכזנו כאן כמה דוגמאות לקוד שיעזרו לכם להתחיל:

פיתוח אתרים

כדי להגדיר את הערכים האלה בשולח אינטרנט של Cast, קודם יוצרים אובייקט MediaInfo עם הנתונים הנדרשים, ואז שולחים בקשת טעינה למקלט האינטרנט.

// Create mediaInfo object
const mediaInfo = new chrome.cast.media.MediaInfo("CONTENT_ID");
mediaInfo.contentUrl = "BACKUP_STREAM_URL";
mediaInfo.contentType = "CONTENT_STREAM_MIMETYPE";
mediaInfo.streamType = chrome.cast.media.StreamType.LIVE;
mediaInfo.customData = {
  daiStreamType: "DAI_STREAM_TYPE",
  networkCode: "NETWORK-CODE",
  customAssetKey: "CUSTOM_ASSET_KEY",
  apiKey: "API_KEY"
};

// Make load request to cast web receiver
const castSession = cast.framework.CastContext.getInstance().getCurrentSession();
const request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  () => { console.log('Load succeed'); },
  (errorCode) => { console.log('Error code: ' + errorCode); });

Android

כדי להגדיר את הערכים האלה בשולח אינטרנט של Cast, קודם יוצרים אובייקט MediaInfo עם הנתונים הנדרשים, ואז שולחים בקשת טעינה למקלט האינטרנט.

JSONObject customData = new JSONObject()?
  .put("daiStreamType", "DAI_STREAM_TYPE")
  .put("networkCode", "NETWORK-CODE")
  .put("customAssetKey", "CUSTOM_ASSET_KEY")
  .put("apiKey", "API_KEY");
MediaInfo mediaInfo = MediaInfo.Builder("CONTENT_ID")
  .setContentUrl("BACKUP_STREAM_URL")
  .setContentType("CONTENT_STREAM_MIMETYPE")
  .setStreamType(MediaInfo.STREAM_TYPE_LIVE)
  .setCustomData(customData)
  .build();

RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());

‫iOS ‏ (Obj-C)

כדי להגדיר את הערכים האלה בשולח אינטרנט של Cast, קודם יוצרים אובייקט GCKMediaInformation עם הנתונים הנדרשים, ואז שולחים בקשת טעינה למקלט האינטרנט.

NSURL url = [NSURL URLWithString:@"BACKUP_STREAM_URL"];
NSDictionary *customData = @{
  @"daiStreamType": @"DAI_STREAM_TYPE",
  @"networkCode": @"NETWORK-CODE",
  @"customAssetKey": @"CUSTOM_ASSET_KEY",
  @"apiKey": @"API_KEY"};
mediaInfoBuilder.customData = customData;

GCKMediaInformationBuilder *mediaInfoBuilder =
  [[GCKMediaInformationBuilder alloc] initWithContentID: @"CONTENT_ID"];
mediaInfoBuilder.contentURL = url;
mediaInfoBuilder.contentType = @"CONTENT_STREAM_MIMETYPE";
mediaInfoBuilder.streamType = GCKMediaStreamTypeLive;
mediaInfoBuilder.customData = customData;
self.mediaInformation = [mediaInfoBuilder build];

GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation];
if (request != nil) {
  request.delegate = self;
}

‫iOS (Swift)

כדי להגדיר את הערכים האלה בשולח אינטרנט של Cast, קודם יוצרים אובייקט GCKMediaInformation עם הנתונים הנדרשים, ואז שולחים בקשת טעינה למקלט האינטרנט.

let url = URL.init(string: "BACKUP_STREAM_URL")
guard let mediaURL = url else {
  print("invalid mediaURL")
  return
}

let customData = [
  "daiStreamType": "DAI_STREAM_TYPE",
  "networkCode": "NETWORK-CODE",
  "customAssetKey": "CUSTOM_ASSET_KEY",
  "region": "API_KEY"
]

let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentId: "CONTENT_ID")
mediaInfoBuilder.contentURL = mediaUrl
mediaInfoBuilder.contentType = @"CONTENT_STREAM_MIMETYPE"
mediaInfoBuilder.streamType = GCKMediaStreamType.Live
mediaInfoBuilder.customData = customData
mediaInformation = mediaInfoBuilder.build()

guard let mediaInfo = mediaInformation else {
  print("invalid mediaInformation")
  return
}

if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia
(mediaInfo) {
  request.delegate = self
}

כלי CAC

כדי להגדיר את הערכים האלה בכלי Cast Command and Control, לוחצים על הכרטיסייה Load Media (טעינת מדיה) ומגדירים את סוג בקשת הטעינה המותאמת אישית ל-LOAD. לאחר מכן מחליפים את נתוני ה-JSON באזור הטקסט ב-JSON הבא:

{
  "media": {
    "contentId": "CONTENT_ID",
    "contentUrl": "BACKUP_STREAM_URL",
    "contentType": ""CONTENT_STREAM_MIMETYPE"",
    "streamType": "LIVE",
    "customData": {
      "daiStreamType": "DAI_STREAM_TYPE",
      "networkCode": "NETWORK-CODE",
      "customAssetKey": "CUSTOM_ASSET_KEY",
      "oAuthToken": "API_KEY"
    }
  }
}

אפשר לשלוח את בקשת הטעינה המותאמת הזו למקבל כדי לבדוק את שאר השלבים.

יצירת מקלט CAF בסיסי

יוצרים מקלט אינטרנט בהתאמה אישית, כמו שמוסבר במדריך בנושא CAF SDK Custom Web Receiver.

הקוד של המקלט אמור להיראות כך:

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js">
  </script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    // ...
  </script>
</body>
</html>

ייבוא של IMA DAI SDK וקבלת Player Manager

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

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();

    castContext.start();
  </script>
</body>
</html>

אתחול של IMA Stream Manager

מפעילים את IMA Stream Manager.

<html>
<head>
  <script type="text/javascript"
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    castContext.start();
  </script>
</body>
</html>

יצירת Stream Manager Load Interceptor

לפני שהפריטים של המדיה מועברים ל-CAF, צריך ליצור את בקשת הסטרימינג בחוסם (interceptor) של הודעת LOAD.

    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    /**
     * Creates a livestream request object for a Pod Serving stream.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => { /* ... */};

    /**
     * Initates a DAI stream request for the final stream manifest.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {Promise<LoadRequestData>} a promise that resolves to an updated castRequest, containing the DAI stream manifest
     */
    const createDAICastRequest = (castRequest) => {
        return streamManager.requestStream(castRequest, createStreamRequest(castRequest))
          .then((castRequestWithPodStreamData) => {
            console.log('Successfully made DAI stream request.');
            // ...
            return castRequestWithPodStreamData;
          })
          .catch((error) => {
            console.log('Failed to make DAI stream request.');
            // CAF will automatically fallback to the content URL
            // that it can read from the castRequest object.
            return castRequest;
          });
    };

    playerManager.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, createDAICastRequest);

    castContext.start();

יצירת בקשה ליצירת מקור נתונים

משלימים את הפונקציה createStreamRequest כדי ליצור זרם של Pod Serving על סמך בקשת הטעינה של CAF.

    /**
     * Creates a livestream request object for a Pod Serving stream.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => {
      const customData = castRequest.media.customData;
      let streamRequest;
      if (customData.daiStreamType == "LIVE") {
        streamRequest = new google.ima.cast.dai.api.PodStreamRequest();
        streamRequest.customAssetKey = customData.customAssetKey;
        streamRequest.networkCode = customData.networkCode;
        streamRequest.apiKey = customData.apiKey;
      } else if (customData.daiStreamType == "VOD") {
        streamRequest = new google.ima.cast.dai.api.PodVodStreamRequest();
        streamRequest.networkCode = customData.networkCode;
        streamRequest.apiKey = customData.apiKey;
      }
      return streamRequest;
    };

אחזור המניפסט המחובר מ-VTP

אם הבקשה ליצירת מקור נתונים תאושר, תוכלו להשתמש ב-streamManager.getStreamId() כדי לאחזר את מזהה מקור הנתונים. השותף הטכני שלך בתחום הווידאו (VTP) או כלי מותאם אישית לשינוי קובץ מניפסט יספק לך הוראות לאחזור כתובת URL של מניפסט באמצעות מזהה הסטרימינג הזה.

אחרי שמקבלים את כתובת ה-URL של קובץ המניפסט, מחליפים את contentUrl הקיים ב-manifestUrl החדש.

לבסוף, לפני שמחזירים את מניפסט הסטרימינג ששונה, קוראים לשיטה loadStreamMetadata ב-streamManager כדי להודיע ל-IMA SDK שאפשר לבקש בבטחה מטא-נתונים של סטרימינג. הקריאה הזו נדרשת רק לשידורי VOD.

    /**
     * Initates a DAI stream request for the final stream manifest.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {Promise<LoadRequestData>} a promise that resolves to an updated castRequest, containing the DAI stream manifest
     */
    const createDAICastRequest = (castRequest) => {
        return streamManager.requestStream(castRequest, createStreamRequest(castRequest))
          .then((castRequestWithPodStreamData) => {
            console.log('Successfully made DAI stream request.');

            // This is a sample VTP integration. Consult your VTP documentation
            // for how to retrieve an ad-stitched stream manifest URL.
            const manifestTemplate = "https://.../manifest.m3u8?gam_stream_id=[[STREAMID]]";
            const streamId = streamManager.getStreamId();
            const manifestUrl = manifestTemplate.replace('[[STREAMID]]', streamId)
            // Assign your manifestUrl to the request's content URL.
            castRequestWithPodStreamData.media.contentUrl = manifestUrl;

            // After generating the manifest URL, VOD streams must notify the
            // IMA SDK that it is safe to request ad pod metadata.
            // This is only necessary for VOD streams. It is a no-op for
            // livestreams, so no conditional is needed.
            streamManager.loadStreamMetadata();

            return castRequestWithPodStreamData;
          })
          .catch((error) => {
            console.log('Failed to make DAI stream request.');
            // CAF will automatically fallback to the content URL
            // that it can read from the castRequest object.
            return castRequest;
          });
    };

לפנות נכסים ב-IMA DAI

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