向网络接收器添加 Ad Breaks API 支持

1. 概览

Google Cast 徽标

此 Codelab 概述了如何构建使用 Cast Ad Breaks API 的自定义网络接收器应用。

什么是 Google Cast?

Google Cast 可让用户将移动设备上的内容投射到电视上。然后,用户可以将其移动设备用作遥控器,来控制电视上的媒体播放。

借助 Google Cast SDK,您可以扩展应用以控制电视或音响系统。借助 Cast SDK,您可以根据 Google Cast 设计核对清单添加必要的界面组件。

Google Cast 设计核对清单旨在实现 Cast 实现标准化,从而在所有支持的平台上提供直观的用户体验。

构建目标

完成此 Codelab 后,您就构建了一个利用 Break API 的 Cast 接收器。

学习内容

  • 如何在 Cast 内容中添加 VMAP 和 VAST 广告插播时间点
  • 如何跳过插播时间点剪辑
  • 如何自定义跳转时的默认中断行为

所需条件

体验

在继续学习此 Codelab 之前,请确保您具有以下体验。

  • 具备一般 Web 开发知识。
  • 构建 Cast Web 接收器应用。

您打算如何使用本教程?

仅阅读教程内容 阅读并完成练习

您如何评价自己在构建 Web 应用方面的经验水平?

新手 中级 熟练

2. 获取示例代码

将所有示例代码下载到您的计算机...

然后解压下载的 zip 文件。

3. 在本地部署接收器

为了能够将网络接收器与 Cast 设备搭配使用,需要将该网络接收器托管在 Cast 设备可以访问的位置。如果您拥有支持 https 的服务器,请跳过以下说明并记下网址,因为下一部分需要用到该网址。

如果您没有可以使用的服务器,则可以使用 Firebase Hostingngrok

运行服务器

设置好您选择的服务后,请前往 app-start 并启动您的服务器。

记下托管接收器的网址。您将在下一部分中用到它。

4. 在 Cast Developer Console 中注册应用

您必须注册应用,才能在 Chromecast 设备上运行此 Codelab 内置的自定义接收器。您注册应用后,系统会生成一个应用 ID,您必须先配置发送应用 ID,然后才能启动网络接收器应用。

Google Cast SDK Developer Console 的图片,其中显示了“添加新应用”字样按钮处于突出显示状态

点击“添加新应用”

“新建接收器应用”的图片显示“Custom Receiver”的屏幕突出显示的选项

选择“Custom Receiver”,这是我们正在构建的内容。

“新建自定义接收器”的图片屏幕,显示了用户在“接收器应用网址”中输入的网址字段

输入新收款方的详细信息。请务必使用指向您计划托管 Web 接收器应用的网址。注册应用后,请记下由控制台生成的应用 ID。发送者应用将在稍后部分中配置为使用该标识符。

此外,您还必须注册 Google Cast 设备,以便该设备可以在您发布接收器应用之前对其进行访问。接收器应用发布后,便可供所有 Google Cast 设备使用。在此 Codelab 中,建议使用未发布的接收器应用。

Google Cast SDK Developer Console 的图片,上面显示“Add New Device”按钮处于突出显示状态

点击“添加新设备”

“添加 Cast 接收器设备”的图片对话框

输入印在 Cast 设备背面的序列号,并为其指定一个描述性名称。访问 Google Cast SDK Developer Console 时,您也可以将屏幕投放到 Chrome 中,从而找到序列号

接收器和设备需要 5-15 分钟才能准备好进行测试。等待 5-15 分钟后,您必须重新启动投放设备。

5. 准备启动项目

在开始此 Codelab 之前,建议您先查看广告开发者指南,其中简要介绍了广告插播时间点 API。

需要在您下载的起始应用中添加对 Google Cast 的支持。以下是此 Codelab 中使用的一些 Google Cast 术语:

  • 发送设备应用是指在移动设备或笔记本电脑上运行的应用;
  • 接收设备应用是指在 Google Cast 设备上运行的应用。

现在,您可以使用自己喜欢的文本编辑器在入门级项目的基础上进行构建了:

  1. 从下载的示例代码中选择 文件夹图标app-start 目录。
  2. 打开 js/receiver.js 和 index.html

请注意,在您完成此 Codelab 的过程中,您选择的网站托管解决方案应该随所做出的更改而更新。在继续验证和测试更改时,请务必将更改推送到托管网站。

应用设计

如前所述,此 Codelab 利用发送器应用启动 Cast 会话,以及一个接收端应用(将修改为使用广告插播时间点 API)。

在此 Codelab 中,Cast and Command Tool 将充当 Web Sender,用于启动接收器应用。首先,在 Chrome 浏览器中打开该工具。输入您在 Cast SDK Developer Console 上获得的接收器应用 ID,然后点击设置以配置发送器应用以进行测试。

注意:如果您发现系统没有显示投放图标,请确保网络接收器和投放设备已在 Cast Developer Console 中正确注册。重启刚刚注册的投放设备(如果您尚未重启)。

接收器应用是此 Codelab 的重点,由 index.html 中定义的一个主视图和一个名为 js/receiver.js 的 JavaScript 文件组成。下文对这些方式进行了详细说明。

index.html

此 HTML 文件包含由 cast-media-player 元素提供的接收器应用的界面。它还会加载 CAF SDK 和 Cast Debug Logger 库。

receiver.js

此脚本管理接收器应用的所有逻辑。现在,它包含一个基本的 CAF 接收器,用于初始化投射上下文并在初始化时加载视频资源。我们还添加了一些调试日志记录器功能,以便向 Cast 和命令工具提供日志记录。

6. 为您的内容添加 VMAP

Cast Web Receiver SDK 支持通过数字视频多广告播放列表(也称为 VMAP)指定的广告。XML 结构可指定媒体的广告插播时间点及其关联的插播时间点剪辑元数据。为了插入这些广告,SDK 会在 MediaInformation 对象中提供 vmapAdsRequest 属性。

js/receiver.js 文件中,创建一个 VastAdsRequest 对象。找到 LOAD 请求拦截器函数并将其替换为以下代码。其中包含一个来自 DoubleClick 的 VMAP 代码网址示例,并提供一个随机 correlator 值,以确保针对同一网址的后续请求会生成包含尚未观看的广告插播时间点的 XML 模板。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      castDebugLogger.info('MyAPP.LOG', 'Intercepting LOAD request');

      // Create the VMAP Ads request data and append it to the MediaInformation.
      const vmapUrl =
          'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&vid=short_onecue&correlator=' +
          Math.floor(Math.random() * Math.pow(10, 10));
      let vmapRequest = new cast.framework.messages.VastAdsRequest();
      vmapRequest.adTagUrl = vmapUrl;
      loadRequestData.media.vmapAdsRequest = vmapRequest;

      castDebugLogger.warn(
          'MyAPP.LOG', 'Playable URL: ' + loadRequestData.media.contentId);

      return loadRequestData;
    });

保存对 js/receiver.js 所做的更改,并将文件上传到您的网络服务器。点击“投射”图标,在投射和命令工具上启动投射会话。VMAP 广告应在播放主要内容之后播放。

7. 将 VAST 添加到您的内容中

如前所述,Web Receiver SDK 支持多种类型的广告。本部分重点介绍了可用于集成数字视频广告投放模板广告(也称为 VAST)的 API。如果您已实现上一部分中的 VMAP 代码,请将其注释掉。

将以下内容复制到 js/receiver.js 文件中的 load 请求拦截器后面。其中包含来自 DoubleClick 的 6 个 VAST 广告插播时间点和一个随机 correlator 值。系统会将这些广告插播剪辑分配到 5 个广告插播时间点。每个广告插播时间点的 position 设置为一个相对于主要内容的时间(以秒为单位),包括前贴片广告(position 设置为 0)和后贴片广告(position 设置为 -1)广告插播时间点。

const addVASTBreaksToMedia = (mediaInformation) => {
  mediaInformation.breakClips = [
    {
      id: 'bc1',
      title: 'bc1 (Pre-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('preroll')
      }
    },
    {
      id: 'bc2',
      title: 'bc2 (Mid-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('midroll')
      }
    },
    {
      id: 'bc3',
      title: 'bc3 (Mid-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('midroll')
      }
    },
    {
      id: 'bc4',
      title: 'bc4 (Mid-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('midroll')
      }
    },
    {
      id: 'bc5',
      title: 'bc5 (Mid-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('midroll')
      }
    },
    {
      id: 'bc6',
      title: 'bc6 (Post-roll)',
      vastAdsRequest: {
        adTagUrl: generateVastUrl('postroll')
      }
    }
  ];

  mediaInformation.breaks = [
    {id: 'b1', breakClipIds: ['bc1'], position: 0},
    {id: 'b2', breakClipIds: ['bc2'], position: 15},
    {id: 'b3', breakClipIds: ['bc3', 'bc4'], position: 60},
    {id: 'b4', breakClipIds: ['bc5'], position: 100},
    {id: 'b5', breakClipIds: ['bc6'], position: -1}
  ];
};

注意:广告插播时间点的 breakClipIds 属性是一个数组,这意味着可以为每个广告插播时间点分配多个广告插播剪辑。

js/receiver.js file 中,找到 LOAD 消息拦截器,并将其替换为以下代码。请注意,为展示 VAST 类型的广告,VMAP 工作会被注释掉。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      castDebugLogger.info('MyAPP.LOG', 'Intercepting LOAD request');

      // Create the VMAP Ads request data and append it to the MediaInformation.
      // const vmapUrl =
      //     'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&vid=short_onecue&correlator=' +
      //     Math.floor(Math.random() * Math.pow(10, 10));
      // let vmapRequest = new cast.framework.messages.VastAdsRequest();
      // vmapRequest.adTagUrl = vmapUrl;
      // loadRequestData.media.vmapAdsRequest = vmapRequest;

      // Append VAST ad breaks to the MediaInformation.
      addVASTBreaksToMedia(loadRequestData.media);

      castDebugLogger.warn(
          'MyAPP.LOG', 'Playable URL: ' + loadRequestData.media.contentId);

      return loadRequestData;
    });

保存对 js/receiver.js 所做的更改,并将文件上传到您的网络服务器。点击“投射”图标,在投射和命令工具上启动投射会话。VAST 广告应在播放主要内容之后播放。

8. 广告插播时间点跳过

CAF 有一个名为 BreakManager 的类,可帮助您为广告行为实施自定义业务规则。其中一项功能可让应用根据某些条件以编程方式跳过插播时间点和插播剪辑。此示例展示了如何跳过位置在内容前 30 秒内(但未在后贴片广告插播时间点之内)的广告插播时间点。使用上一部分中配置的 VAST 广告时,定义了 5 个广告插播时间点:1 个前贴片广告插播时间点、3 个中贴片广告插播时间点(15 秒、60 秒和 100 秒处),以及一个后贴片广告插播时间点。完成上述步骤后,系统只会跳过位置在 15 秒处的前贴片广告中贴片广告

为此,应用应调用通过 BreakManager 提供的 API,以设置用于中断加载的拦截器。将下面这行代码复制到 js/receiver.js 文件中包含 contextplayerManager 变量的行后面,以获取对实例的引用。

const breakManager = playerManager.getBreakManager();

应用应设置一个拦截器,并采用以下规则:忽略 30 秒之前出现的任何广告插播时间点,同时注意所有后贴片广告插播时间点(因为它们的 position 值为 -1)。此拦截器的工作方式类似于 PlayerManager 上的 LOAD 拦截器,不同之处在于此拦截器专用于加载中断剪辑。在 LOAD 请求拦截器之后、addVASTBreaksToMedia 函数声明之前设置此属性。

将以下内容复制到 js/receiver.js 文件中。

breakManager.setBreakClipLoadInterceptor((breakClip, breakContext) => {
  /**
   * The code will skip playback of break clips if the break position is within
   * the first 30 seconds.
   */
  let breakObj = breakContext.break;
  if (breakObj.position >= 0 && breakObj.position < 30) {
    castDebugLogger.debug(
        'MyAPP.LOG',
        'Break Clip Load Interceptor skipping break with ID: ' + breakObj.id);
    return null;
  } else {
    return breakClip;
  }
});

注意:此处返回 null 会跳过正在处理的 BreakClip。如果 Break 未定义任何广告插播时间点,则系统会跳过广告插播时间点本身。

保存对 js/receiver.js 所做的更改,并将文件上传到您的网络服务器。点击“投射”图标,在投射和命令工具上启动投射会话。VAST 广告应得到处理。请注意,系统不会播放前贴片广告和第一个中贴片广告position 为 15 秒)。

9. 自定义中断跳转行为

在跳转过去的广告插播时间点时,默认实现会获取位置介于跳转操作的 seekFromseekTo 值之间的所有 Break 项。在此插播列表中,SDK 会播放 position 最接近 seekTo 值且 isWatched 属性设置为 falseBreak。然后,系统会将该广告插播时间点的 isWatched 属性设置为 true,然后播放器开始播放其广告插播片段。看完插播广告后,主要内容会从 seekTo 位置继续播放。如果不存在此类插播,则不播放任何插播,并且主要内容会在 seekTo 位置继续播放。

为了自定义在跳转时播放的具体中断,Cast SDK 在 BreakManager 中提供了 setBreakSeekInterceptor API。当应用通过该 API 提供其自定义逻辑时,每当在一个或多个停顿中执行跳转操作时,SDK 都会调用该逻辑。系统会向回调函数传递一个对象,其中包含 seekFrom 位置和 seekTo 位置之间的所有断点。然后,应用需要修改并返回 BreakSeekData

为了说明其用法,以下示例将替换默认行为,具体方法为:替换所有已跳转的停顿,并仅播放时间轴中显示的第一个停顿。

将以下内容复制到 js/receiver.js 文件中定义下的 setBreakClipLoadInterceptor 中。

breakManager.setBreakSeekInterceptor((breakSeekData) => {
  /**
   * The code will play an unwatched break between the seekFrom and seekTo
   * position. Note: If the position of a break is less than 30 then it will be
   * skipped due to the setBreakClipLoadInterceptor code.
   */
  castDebugLogger.debug(
      'MyAPP.LOG',
      'Break Seek Interceptor processing break ids ' +
          JSON.stringify(breakSeekData.breaks.map(adBreak => adBreak.id)));

  // Remove all other breaks except for the first one.
  breakSeekData.breaks.splice(1,breakSeekData.breaks.length);
  return breakSeekData;
});

注意:如果函数不返回值或返回 null,则不会播放插播时间点。

保存对 js/receiver.js 所做的更改,并将文件上传到您的网络服务器。点击“投射”图标,在投射和命令工具上启动投射会话。VAST 广告应得到处理。请注意,系统不会播放前贴片广告和第一个中贴片广告position 为 15 秒)。

等待播放时间达到 30 秒,以跳过由广告插播片段加载拦截器跳过的所有广告插播时间点。到达后,转到媒体控制标签页来调度跳转命令。使用 300 秒填充 Seek Into Media 输入,然后点击 TO 按钮。请注意 Break Seek Interceptor 中输出的日志。现在,应替换默认行为,以便在接近 seekFrom 时间时播放广告插播时间点。

10. 恭喜

您现在已经知道如何使用最新的 Cast 接收器 SDK 向接收器应用添加广告了。

如需了解详情,请参阅广告插播时间点开发者指南。