1. 概览
在此 Codelab 中,您将了解如何构建使用 Cast Ad Breaks API 的自定义 Web 接收器应用。
什么是 Google Cast?
Google Cast 可让用户将移动设备上的内容投射到电视上。然后,用户可以将其移动设备用作遥控器,来控制电视上的媒体播放。
借助 Google Cast SDK,您可以扩展应用以控制电视或音响系统。借助 Cast SDK,您可以根据 Google Cast 设计核对清单添加必要的界面组件。
Google Cast 设计核对清单用于在所有支持的平台上实现简单、可预测的 Cast 用户体验。
构建目标
完成此 Codelab 后,您将构建一个利用新的 Break API 的 Cast 接收器。
学习内容
- 如何在投放内容中添加 VMAP 和 VAST 广告插播时间点
- 如何跳过广告插播时间点
- 如何自定义跳转的默认中断行为
所需条件
- 最新版本的 Google Chrome 浏览器。
- HTTPS 托管服务,例如 Firebase Hosting 或 ngrok。
- 具有互联网访问权限的 Chromecast 或 Android TV 等 Google Cast 设备。
- 带 HDMI 输入端口的电视或显示器,或 Google Home Hub
体验
- 您需要具备网络开发知识。
- 拥有构建 Cast 发送器和接收器应用的经验。
您打算如何使用本教程?
您如何评价自己在构建 Web 应用方面的经验水平?
2. 获取示例代码
您可以将所有示例代码下载到您的计算机…
然后解压下载的 zip 文件。
3. 在本地部署接收器
若要将网络接收器与 Cast 设备搭配使用,需要将其托管在 Cast 设备可以访问的位置。如果您已有支持 https 的服务器,请跳过以下说明并记下该网址,因为下一部分需要用到该网址。
如果您没有可供使用的服务器,则可以使用 Firebase Hosting 或 ngrok。
运行服务器
设置完您所选的服务后,请转到 app-start
并启动您的服务器。
记下托管接收器的网址。您将在下一部分中使用它。
4. 在 Cast 开发者控制台中注册应用
您必须注册您的应用,才能在 Chromecast 设备上运行自定义接收器(如此 Codelab 中所构建)。注册您的应用后,您会收到一个应用 ID,发送者的应用必须使用该 ID 来执行 API 调用,例如启动接收器应用。
点击“添加新应用”
选择“Custom Receiver”(自定义接收器),这就是我们正在构建的应用。
输入新接收器的详细信息,请务必使用您最终选择的网址
(在上一部分中)。记下分配给全新接收器的应用 ID。
此外,您必须注册 Google Cast 设备,才能让该设备访问您的接收器应用,然后再发布该应用。您发布接收器应用后,便可在所有 Google Cast 设备上使用。在此 Codelab 中,建议使用未发布的接收器应用。
点击“添加新设备”
输入印在设备背面的序列号,并为其指定一个描述性名称。访问 Google Cast SDK 管理中心时,您也可在 Chrome 中投射屏幕,从而找到您的序列号
接收器和设备需要 5-15 分钟才能准备好进行测试。等待 5-15 分钟后,您必须重新启动自己的投放设备。
5. 准备起始项目
在开始此 Codelab 之前,您不妨参阅广告开发者指南,其中简要介绍了新广告功能。
我们需要在您下载的入门级应用中添加 Google Cast 支持。以下是我们将在此 Codelab 中使用的一些 Google Cast 术语:
- 发送设备应用是指在移动设备或笔记本电脑上运行的应用;
- 接收设备应用是指在 Google Cast 设备上运行的应用。
现在,您可以使用自己喜爱的文本编辑器基于入门级项目进行构建了:
- 从下载的示例代码中选择
app-start
目录。 - 打开
js/receiver.js
和 index.html
请注意,在学习此 Codelab 的过程中,http-server
应该会捕捉您的更改。如果发现未启动,请尝试终止并重启 http-server
。
对于我们的发送器,我们将使用 CAF 接收器调试功能来启动投放会话。接收器设计为自动开始播放直播。
应用设计
接收器应用会初始化投放会话,并一直处于待机状态,直到收到某个发送者的 LOAD 请求(即播放媒体内容的命令)。
该应用由一个主视图(在 index.html
中定义)和一个名为 js/receiver.js
的 JavaScript 文件组成,该文件包含使接收器正常运行的所有逻辑。
index.html
此 HTML 文件将包含接收方应用的所有界面。目前,该文件基本上是空的。
接收器.js
此脚本管理将管理接收器应用的所有逻辑。目前,它包含一个基本的 CAF 接收器。
6. 将 VMAP 添加到您的内容中
首先,在 Chrome 中打开网页发件人。输入您在 Cast SDK Console 中提供的接收器应用 ID,然后点击“设置”。
在接收器中,我们需要添加一些逻辑以在内容中添加广告。
将以下行复制到 js/receiver.js
文件中。它包含来自 DoubleClick 的 VMAP 代码链接示例和一些随机示例。
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));
在 js/receiver.js file
中,找到 playerManager.setMessageInterceptor
函数,并在函数中最后一行 return request;
前面添加以下代码。
request.media.vmapAdsRequest = {
adTagUrl: vmapUrl,
};
注意:上面分配给 vmapAdsRequest
的对象是 VastAdsRequest 对象的简写版本。
保存对 js/receiver.js
的更改,并在网页发送者上发起投放会话,方法是右键点击网页上的任意位置,然后选择“投放”。广告流应该会立即开始播放。
7. 将 VAST 添加到您的内容中
如果您已实现上述 VMAP 代码,请注释掉。下文将介绍如何在内容中植入 VAST 广告。
将以下内容复制到 js/receiver.js
文件中。它包含来自 DoubleClick 的 6 个 VAST 广告插播时间点片段,以及一些随机片段。系统会将这些剪辑片段分配给 5 个广告插播时间点。此外,还指定了每个广告插播时间点的位置。
const addVASTBreaksToMedia = (mediaInformation) => {
mediaInformation.breakClips = [
{
id: "bc1",
title: "bc1 (Pre-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&vad_type=linear&vpos=preroll&pod=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
},
{
id: "bc2",
title: "bc2 (Mid-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&rmridx=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
},
{
id: "bc3",
title: "bc3 (Mid-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&rmridx=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
},
{
id: "bc4",
title: "bc4 (Mid-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&rmridx=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
},
{
id: "bc5",
title: "bc5 (Mid-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&rmridx=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
},
{
id: "bc6",
title: "bc6 (Post-roll)",
vastAdsRequest: {
adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&url=&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&vad_type=linear&vpos=postroll&pod=3&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6256&correlator=' + Math.floor(Math.random() * Math.pow(10, 10)) + '&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0'
}
}
];
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 消息拦截器(也就是以 playerManager.setMessageInterceptor
开头的行),并在函数中最后的 return request;
行之前添加以下内容。
addVASTBreaksToMedia(request.media);
保存对 js/receiver.js
的更改,并在网页发送者上发起投放会话,方法是右键点击网页上的任意位置,然后选择“投放”。广告流应该会立即开始播放。
8. 跳过广告插播时间点
CAF 有一个名为“BreakManager”的新类,可帮助您实现针对广告行为的自定义业务规则。假设您希望让客户在一段特定时间后跳过某些广告。
在此示例中,发送者没有媒体控件。我们来添加 10 秒的起始偏移量,以便视频流在前贴片广告之后、第一个中贴片广告插播时间点在 15 秒标记之前开始播放。
找到 playerManager.setMessageInterceptor
,并在 return request
之前添加以下这行代码。
request.currentTime = 10;
保存 receiver.js
文件并启动投放会话。您应该会在内容加载 10 秒钟后看到广告,然后在 5 秒钟后播放广告。
现在,我们来添加一条规则,在 15 秒处跳过中贴片广告。
您需要一个 BreakManager 实例来为中断加载设置拦截器。将以下代码行复制到 js/receiver.js
文件中,其中包含 context
和 playerManager
变量的行。
const breakManager = playerManager.getBreakManager();
现在,让我们使用规则来设置拦截器,以忽略 30 秒之前发生的任何广告插播时间点。该拦截器的工作原理与 PlayerManager 上的 LOAD 拦截器类似,只不过它专门用于加载 BreakClip。
将以下内容复制到 js/receiver.js
文件中。
breakManager.setBreakClipLoadInterceptor((breakClip, breakCtx) => {
/** Below code will skip playback of break clips if the break position is less than 30 **/
let breakObj = breakCtx.break;
if(breakObj.position < 30)
return null;
else
return breakClip;
});
注意:对于应跳过的 BreakClip,我们会在此处返回 null。
保存对 js/receiver.js
的更改,并在网页发送者上发起投放会话,方法是右键点击网页上的任意位置,然后选择“投放”。
视频流应该开始播放,但是我们会跳过之前播放的广告片段(在 15 秒后展示)。
9. 自定义广告插播时间点行为
当用户快进时,跳转时间和跳转时间之间的最后一个未播放广告插播时间点会在内容从跳转时间点开始播放之前播放。当用户快退时,不会播放任何广告插播时间点。这是默认的中断行为。
我们利用 BreakManager 来自定义在道上播放的广告插播时间点。我们使用 BreakManager 的 setBreakSeekInterceptor 指定我们想要的自定义行为。每次执行跳转操作时,都会调用 setBreakSeekInterceptor。
我们将一个回调函数传递给 setBreakSeekInterceptor。系统会向回调函数传递一个对象,其中包含跳转位置和跳转位置之间的所有分隔符。
现在,我们来设置一个拦截器,并使用规则播放尚未在“fromFrom”和“toTo”位置之间播放的广告插播时间点。
将以下内容复制到 js/receiver.js
文件中。
breakManager.setBreakSeekInterceptor(function(breakSeekData) {
/**
*
* Below code will play an unwatched break between 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
*/
let breakToPlay;
for (let i = 0; i < breakSeekData.breaks.length; i++) {
if (!breakSeekData.breaks[i].isWatched) {
breakToPlay = breakSeekData.breaks[i];
}
}
if (breakToPlay){
breakSeekData.breaks = [breakToPlay];
return breakSeekData;
}
});
注意:如果我们不返回任何值/null,就不会播放任何中断。如果我们按原样返回 breakSeekData,则跳转到跳转之间的所有时间点都会播放。
保存对 js/receiver.js
的更改,并在网页发送者上发起投放会话,方法是右键点击网页上的任意位置,然后选择“投放”。广告流应该会立即开始播放。
10. 恭喜
现在,您已了解如何使用最新的 Cast Receiver SDK 向接收方应用添加广告。
如需了解详情,请参阅广告插播时间点开发者指南。