开始使用 IMA DAI SDK

选择您感兴趣的 DAI 解决方案

Pod 投放 DAI

IMA SDK 可简化将多媒体广告集成到您的网站和应用中的操作。

IMA SDK 可以从任何符合 VAST 标准的广告服务器中请求广告,并在您的应用中管理广告播放。

借助 IMA DAI SDK,应用可针对 VOD 或直播内容的广告和内容视频发出流请求。然后,SDK 会返回一个组合的视频流,这样您就不必在应用内管理广告和内容视频之间的切换了。

本指南演示了如何使用 IMA DAI SDK for CAF 播放直播 DAI Pod Serving 流。

使用本指南之前,请先熟悉 Chromecast 应用框架的 Web 接收器协议。本指南假定您对 CAF 接收器概念(例如消息拦截器mediaInformation 对象)有基本的了解,并熟悉如何使用 Cast 命令和控制工具来模拟 CAF 发送器。

若要使用 IMA DAI Pod 投放,您必须与 Pod 投放合作伙伴合作,并且必须拥有 Ad Manager 360 高级版帐号。如果您有 Ad Manager 账号,请与您的客户经理联系以了解详情。如需了解如何注册 Ad Manager,请访问 Ad Manager 帮助中心

如需了解如何与其他平台集成或如何使用 IMA 客户端 SDK,请参阅互动式媒体广告 SDK

IMA DAI Pod Serving 概览

使用 IMA CAF DAI SDK 实现 Pod 投放涉及两个主要组件,本指南对此进行了演示:

  • StreamRequest:用于定义发送到 Google 广告服务器的流请求的对象。请求指定网络代码、自定义资产键、可选 API 密钥以及其他可选参数。
  • StreamManager:用于处理视频流与 IMA DAI SDK 之间的通信(例如触发跟踪 ping 和将视频流事件转发给发布商)的对象。

前提条件

  • 一个 Cast 开发者控制台帐号,其中包含已注册的测试设备。
  • 一个已向 Cast Developer Console 注册的托管式网络接收器应用,该应用可以修改以托管本指南提供的代码。
  • 一个配置为使用网络接收器应用的发送应用。出于本示例的目的,请使用 Cast 命令和控制工具作为发送器。

配置发送者的 MediaInfo 对象

首先,配置发送者应用的 MediaInfo 对象以包含以下字段:

野战 内容
contentId 此媒体项的唯一标识符。

CONTENT_ID

contentUrl 可选。DAI 视频流加载失败时播放的备用视频流网址。

BACKUP_STREAM_URL

contentType 可选。内容备用视频流的 MIME 类型。仅 DASH 流需要。

CONTENT_STREAM_MIMETYPE

streamType 用于此值的字符串字面量或常量因发件人平台而异。
customData customData 字段包含用于存储其他必填字段的键值对。
野战 内容
manifestUrl 由清单操纵器或第三方合作伙伴提供的视频流网址。您应在发出请求之前,插入由 IMA DAI SDK 提供的视频流 ID。在此示例中,清单网址包含一个占位符 [[STREAMID]],它会在发出请求之前替换为数据流 ID。

MANIFEST_URL

networkCode 您的 Google Ad Manager 360 帐号的广告联盟代码。

NETWORK_CODE

customAssetKey 自定义素材资源键,用于在 Google Ad Manager 360 中标识 Pod 投放事件。在某些情况下,您可以通过清单操纵器或第三方 Pod 投放合作伙伴获取此信息。

CUSTOM_ASSET_KEY

apiKey 可选的 API 密钥,用于从 IMA DAI SDK 中检索视频流 ID。

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 = {
manifestUrl: "MANIFEST_URL",
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("manifestUrl", "MANIFEST_URL")
  .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 = @{
  @"manifestUrl": @"MANIFEST_URL",
  @"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 = [
  "liveConfigID": "MANIFEST_URL",
  "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 命令和控制工具中配置这些值,请点击“加载媒体”标签页,然后将自定义加载请求类型设置为“加载”。然后,将文本区域中的 JSON 数据替换为以下 JSON:

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

此自定义加载请求可以发送给接收器,以测试其余步骤。

创建基本 CAF 接收器

创建自定义 Web 接收器,如 CAF SDK 自定义 Web 接收器指南中所述。

您的接收器代码应如下所示:

<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 并获取播放器管理器

添加脚本代码,用于在脚本加载 CAF 之后将适用于 CAF 的 IMA DAI SDK 导入 Web 接收器。在脚本标记中,在启动接收器之前,将接收器上下文和播放器管理器存储为常量。

<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 视频流管理器

初始化 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>

创建流管理器负载拦截器

在媒体项传递给 CAF 之前,请先在 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 函数,以根据 CAF 加载请求创建 Pod 传送流。

    /**
     * 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 streamRequest = new google.ima.cast.dai.api.PodStreamRequest();
      const customData = castRequest.media.customData;

      streamRequest.customAssetKey = customData.customAssetKey;
      streamRequest.networkCode = customData.networkCode;
      streamRequest.apiKey = customData.apiKey;

      return streamRequest;
    };

将内容网址替换为清单网址和数据流 ID

如果您的流请求成功,请使用 streamManager.getStreamId() 检索该数据流的 ID 并将其插入您的 manifestUrl(替换 [[STREAMID]])。然后,将现有 contentUrl 替换为新的 manifestUrl,以便 CAF 使用拼接的广告连播播放直播。

    /**
     * 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.');
            const media = castRequestWithPodStreamData.media;
                const manifestUrl = media.customData.manifestUrl || "";
                if (manifestUrl) {
                    console.log('Replacing the contentURL with the manifest URL and stream ID');
                    const streamId = streamManager.getStreamId();
                    castRequestWithPodStreamData.media.contentUrl = manifestUrl.replace('[[STREAMID]]', streamId);

            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;
          });
    };

您现在可以使用 Cast 应用框架和 IMA DAI SDK for CAF 请求和播放 Pod 投放数据流。