向网络接收器添加 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 接收器。

学习内容

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

所需条件

体验

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

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

您打算如何使用本教程?

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

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

新手 中等 熟练

2. 获取示例代码

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

然后解压下载的 zip 文件。

3. 在本地部署接收器

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

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

运行服务器

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

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

4. 在 Cast Developer Console 中注册应用

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

Google Cast SDK 开发者控制台的图片,其中突出显示了“添加新应用”按钮

点击“添加新应用”

“新建接收器应用”屏幕的图片,其中突出显示了“自定义接收器”选项

选择“自定义接收器”,这是我们正在构建的接收器。

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

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

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

Google Cast SDK 开发者控制台的图片,其中突出显示了“Add New Device”按钮

点击“添加新设备”

“Add Cast Receiver Device”对话框的图片

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

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

5. 准备 Start 项目

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

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

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

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

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

请注意,在您学习此 Codelab 时,您选择的网站托管解决方案应该会随着所做更改进行更新。确保在继续验证和测试更改时,将更改推送到托管网站。

应用设计

如上所述,此 Codelab 利用发送器应用启动 Cast 会话,利用接收器应用进行修改,以使用广告插播时间点 API。

在此 Codelab 中,投射和命令行工具将充当 Web 发送器,用于启动接收器应用。首先,请在 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 和 Command 工具的日志记录。

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 接收器 SDK 支持多种类型的广告。本部分将重点介绍可用于集成数字视频广告投放模板广告(也称为 VAST)的 API。如果您实现了上一部分中的 VMAP 代码,请将其注释掉。

将以下内容复制到 js/receiver.js 文件中的加载请求拦截器后面。其中包含 6 个来自 DoubleClick 的 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 消息拦截器,并将其替换为以下代码。请注意,VMAP 工作会被注释掉,以展示 VAST 类型广告。

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 秒处),最后 1 个后贴片广告插播时间点。完成上述步骤后,系统只会跳过位置为 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 会播放 Break,其 position 最接近 seekTo 值,且 isWatched 属性设置为 false。然后,该广告插播的 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 将广告添加到接收器应用。

有关详情,请参阅广告插播时间点开发者指南。