1. 概览
在此 Codelab 中,您将学习如何构建自定义网络接收器应用,以在支持 Cast 的设备上播放内容。
什么是 Google Cast?
Google Cast 可让用户将移动设备上的内容投射到电视上。然后,用户可将移动设备或桌面版 Chrome 浏览器用作遥控器,控制电视上的媒体播放。
借助 Google Cast SDK,您的应用可以控制支持 Google Cast 的设备(例如电视或音响系统)。Cast SDK 会根据 Google Cast 设计核对清单为您提供必要的界面组件。
提供 Google Cast 设计核对清单是为了确保在所有支持的平台上都能提供简单且可预测的 Cast 用户体验。点击此处了解详情。
构建目标
完成此 Codelab 后,您将得到一款 HTML5 应用。该应用可充当您自己的自定义接收器,能够在支持 Cast 的设备上显示视频内容。
学习内容
- 如何为接收器开发做好准备。
- 基于 Cast 应用框架且支持 Cast 的接收器的基础知识。
- 如何接收投射的视频。
- 如何集成调试记录器。
- 如何针对智能显示屏优化接收器。
所需条件
- 最新版本的 Google Chrome 浏览器。
- HTTPS 托管服务,例如 Firebase Hosting 或 ngrok。
- 一台可连接到互联网的 Google Cast 设备,例如 Chromecast 或 Android TV。
- 一台带 HDMI 输入端口的电视或显示器。
体验
- 您需要有 Web 开发经验。
- 您还需要有观看电视的经验 :)
您打算如何使用本教程?
您如何评价自己在构建 Web 应用方面的经验水平?
您如何评价自己在观看电视方面的经验水平?
2. 获取示例代码
您可以将所有示例代码下载到您的计算机…
然后解压下载的 zip 文件。
3. 在本地部署接收器
为了能够将网络接收器与 Cast 设备搭配使用,您需要将它托管在 Cast 设备可以访问的某个位置。如果您已有支持 https 的服务器可供使用,请跳过以下说明并记下网址,因为下一部分需要用到该网址。
如果您没有可供使用的服务器,可以使用 Firebase Hosting 或 ngrok。
运行服务器
设置完您选择的服务后,请前往 app-start
并启动服务器。
记下托管接收器的网址。您将在下一部分中使用它。
4. 在 Cast Developer Console 中注册应用
您必须注册应用,才能在 Chromecast 设备上运行此 Codelab 中构建的自定义接收器。注册应用后,您会收到一个应用 ID,发送方应用必须使用该 ID 来执行 API 调用(例如,启动接收方应用)。
点击“添加新应用”
选择“Custom Receiver”,这是我们正在构建的接收器。
输入新接收器的详细信息,请务必使用您最后获得的网址
详细介绍。记下分配给新接收器的应用 ID。
此外,您还必须注册 Google Cast 设备,以便该设备在您发布接收器应用之前对其进行访问。接收器应用发布后,便可供所有 Google Cast 设备使用。在此 Codelab 中,建议使用未发布的接收器应用。
点击“添加新设备”
输入印在 Cast 设备背面的序列号,并为其指定一个描述性名称。您也可以在访问 Google Cast SDK Developer Console 时将屏幕投射到 Chrome 中找到相应序列号
接收器和设备需要 5-15 分钟才能准备好进行测试。等待 5-15 分钟后,您必须重新启动投放设备。
5. 运行示例应用
在等待新接收器应用做好测试准备期间,让我们看看已完成的示例接收器应用是什么样的。我们要构建的接收器将能够使用自适应比特率流式传输播放媒体内容(我们将使用针对 HTTP 动态自适应流式传输 (DASH) 编码的示例内容)。
在浏览器中,打开命令与控制 (CaC) 工具。
- 您应该会看到我们的 CaC 工具。
- 使用默认的“CC1AD845”示例接收器 ID,然后点击“设置应用 ID”按钮。
- 点击左上角的“投放”按钮,然后选择您的 Google Cast 设备。
- 转到顶部的“Load Media”标签页。
- 点击“Load by Content”按钮播放示例视频。
- 该视频将开始在 Google Cast 设备上播放,展示使用默认接收器时的基本接收器功能。
6. 准备起始项目
我们需要在您下载的入门级应用中添加 Google Cast 支持。以下是我们会在此 Codelab 中使用的一些 Google Cast 术语:
- 发送设备应用是指在移动设备或笔记本电脑上运行的应用;
- 接收设备应用是指在 Google Cast 设备上运行的应用。
现在,您可以使用自己喜欢的文本编辑器在入门级项目的基础上进行构建了:
- 从下载的示例代码中选择
app-start
目录。 - 打开
js/receiver.js
和index.html
请注意,在学习此 Codelab 时,http-server
应选择您所做的更改。如果您发现它并未出现,请尝试终止并重启 http-server
。
应用设计
接收器应用初始化 Cast 会话并会一直等待,直到收到发送器的 LOAD 请求(即,播放一段媒体内容的命令)。
该应用包含一个主视图(在 index.html
中定义)和一个名为 js/receiver.js
的 JavaScript 文件,其中包含接收器正常运行所需的全部逻辑。
index.html
此 HTML 文件将包含接收器应用的界面。目前它为空,我们将在整个 Codelab 中向其中添加内容。
receiver.js
此脚本将管理接收器应用的所有逻辑。目前它只是一个空文件,但在下一部分中,我们只需编写几行代码,即可将其变成功能齐全的 Cast 接收器。
7. 基本 Cast 接收器
基本 Cast 接收器将在启动时初始化 Cast 会话。必须这样做,才能告知所有已连接的发送器应用,已成功启动接收器。此外,新的 SDK 已经过预先配置,可直接处理自适应比特率流式传输媒体(使用 DASH、HLS 和 Smooth Streaming)和普通 MP4 文件。我们来试试看。
初始化
将以下代码添加到 index.html
的标头中:
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>
将以下代码添加到 index.html
<body>
的 <footer>
(加载 receiver.js,
)之前,以便为接收器 SDK 提供空间,从而调出您刚添加的脚本随附的默认接收器界面。
<cast-media-player></cast-media-player>
现在,我们需要在 js/receiver.js
中初始化 SDK,其中包括:
- 获取对
CastReceiverContext
(整个接收器 SDK 的主要入口点)的引用 - 存储对
PlayerManager
的引用,该对象负责处理播放并为您提供插入自己的自定义逻辑所需的所有钩子 - 通过对
CastReceiverContext
调用start()
来初始化 SDK
将以下内容添加到 js/receiver.js
。
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. 投射“基本”视频内容
在此 Codelab 中,请使用 CaC 工具试用全新的接收器。
使用网络浏览器访问命令与控制 (CaC) 工具。
请务必将您自己的应用 ID 替换为之前在该字段中注册的应用 ID,然后点击“设置应用 ID”。这会指示该工具在启动 Cast 会话时使用您的接收器。
投射媒体
概括来讲,要在 Cast 设备上播放媒体内容,需要满足以下条件:
- 发送方从 Cast SDK 创建一个为媒体内容建模的
MediaInfo
JSON
对象。 - 发送器连接到 Cast 设备以启动接收设备应用。
- 接收器通过
LOAD
请求加载MediaInfo
对象,以播放内容。 - 接收器监控并跟踪媒体状态。
- 发送器根据用户与发送器应用的互动,向接收器发送播放命令以控制播放。
在第一次基本尝试中,我们将使用可播放资源网址(存储在 MediaInfo.contentUrl
中)填充 MediaInfo
。
在实际应用中,发送器会在 MediaInfo.contentId
中使用应用特定的媒体标识符。接收器使用 contentId
作为标识符来发出适当的后端 API 调用,以解析实际的素材资源网址并将其设为 MediaInfo.contentUrl.
。接收器还将处理一些任务,例如获取 DRM 许可或注入有关广告插播时间点的信息。
在下一部分中,我们将扩展您的接收器,使其执行类似的操作。现在,请点击“投射”图标并选择您的设备以打开接收器。
前往“Load Media”标签页,然后点击“Load by Content”按钮。您的接收器应开始播放示例内容。
接收器 SDK 开箱即可处理:
- 初始化 Cast 会话
- 处理来自包含可播放资源的发送者的传入
LOAD
请求 - 提供可在大屏幕上显示的基本播放器界面。
在继续学习下一部分之前,请随意探索 CaC 工具及其代码。在下一部分,我们将扩展接收器以与简单的示例 API 通信,以实现来自发送器的传入 LOAD
请求。
9. 与外部 API 集成
我们将根据大多数开发者在实际应用中与 Cast 接收器交互的方式修改接收器,以便处理通过 API 密钥引用预期媒体内容(而不是通过可播放资源网址)的 LOAD
请求。
应用这么做通常是因为:
- 发送者可能不知道内容网址。
- Cast 应用旨在直接在接收器上处理身份验证、其他业务逻辑或 API 调用。
此功能主要在 PlayerManager
setMessageInterceptor()
方法中实现。这样,您就可以按类型拦截传入消息,并在消息到达 SDK 的内部消息处理程序之前对其进行修改。在本部分中,我们将处理 LOAD
请求,并且我们将执行以下操作:
- 读取传入的
LOAD
请求及其自定义contentId
。 - 对我们的 API 进行
GET
调用,以按contentId
查找可流式传输的资源。 - 使用流的网址修改
LOAD
请求。 - 修改
MediaInformation
对象以设置数据流类型参数。 - 将请求传递到 SDK 进行播放,或者在我们无法查找所请求的媒体时拒绝该命令。
提供的示例 API 展示了用于自定义常见接收器任务的 SDK 钩子,同时仍然依赖于大部分开箱即用的体验。
示例 API
请通过浏览器访问 https://storage.googleapis.com/cpe-sample-media/content.json,并查看我们的示例视频目录。内容包括 png 格式的海报图片的网址,以及 DASH 和 HLS 数据流的网址。DASH 和 HLS 视频流指向存储在 fragment mp4 容器中的多路分配视频和音频源。
{
"bbb": {
"author": "The Blender Project",
"description": "Grumpy Bunny is grumpy",
"poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
"stream": {
"dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
"hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
"title": "Big Buck Bunny"
},
"fbb_ad": {
"author": "Google Inc.",
"description": "Introducing Chromecast. The easiest way to enjoy [...]",
"poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
"stream": {
"dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
"hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
"title": "For Bigger Blazes"
},
[...]
}
在下一步中,在使用 LOAD
请求调用接收器后,我们将每个条目的键(例如 bbb, fbb_ad
)映射到数据流的网址。
拦截 LOAD 请求
在此步骤中,我们将创建一个加载拦截器,其中包含一个向托管的 JSON
文件发出 XHR
请求的函数。获取 JSON
文件后,我们将解析内容并设置元数据。在以下部分中,我们将自定义 MediaInformation
参数以指定内容类型。
将以下代码添加到 js/receiver.js
文件中,就在对 context.start()
的调用之前。
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
reject();
} else {
// Add metadata
let metadata = new
cast.framework.messages.GenericMediaMetadata();
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
下一部分将概述如何为 DASH 内容配置加载请求的 media
属性。
使用示例 API DASH 内容
现在,我们准备了 load 拦截器,接下来要为接收器指定内容类型。此信息将为接收器提供主播放列表网址和视频流 MIME 类型。将以下代码添加到 js/receiver.js 文件中的 LOAD
拦截器的 Promise()
中:
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
...
}
});
});
});
完成此步骤后,您可以继续“测试”部分,尝试使用 DASH 内容进行加载。如果您想使用 HLS 内容测试加载情况,请查看下一步。
使用示例 API HLS 内容
示例 API 包含 HLS 内容以及 DASH。除了像上一步一样设置 contentType
之外,加载请求还需要一些其他属性,以便使用示例 API 的 HLS 网址。当接收器配置为播放 HLS 视频流时,预期的默认容器类型为传输流 (TS)。因此,如果仅修改了 contentUrl
属性,接收器将尝试以 TS 格式打开示例 MP4 视频流。在加载请求中,应使用其他属性修改 MediaInformation
对象,以便接收方知道内容的类型为 MP4 而非 TS。将以下代码添加到 js/receiver.js 文件中的 load 拦截器中,以修改 contentUrl
和 contentType
属性。此外,还要添加 HlsSegmentFormat
和 HlsVideoSegmentFormat
属性。
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.hls;
request.media.contentType = 'application/x-mpegurl';
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
...
}
});
});
});
开始测试
再次打开命令与控制 (CaC) 工具,然后将您的应用 ID 设置为接收设备的应用 ID。使用“投射”按钮选择您的设备。
前往“Load Media”标签页。这次删除“Load by Content”按钮旁边的“Content 网址”字段中的文本,这会强制应用发送仅包含对媒体的 contentId
引用的 LOAD
请求。
假设对接收器的修改一切正常,拦截器应负责将 MediaInfo
对象调整为 SDK 可在屏幕上播放的内容。
点击“Load by Content”按钮,看看媒体内容能否正常播放。您可以随意在 content.json 文件中将 Content ID 更改为其他 ID。
10. 针对智能显示屏进行优化
智能显示屏是具有触摸功能的设备,可让接收器应用支持触摸式控件。
本部分将介绍如何在接收器应用在智能显示屏上启动时优化该应用,以及如何自定义播放器控件。
访问界面控件
您可以使用 cast.framework.ui.Controls.GetInstance()
访问智能显示屏的界面控件对象。将以下代码添加到 js/receiver.js
文件中的 context.start()
上方:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
context.start();
如果您不使用 <cast-media-player> 元素,则需要在 CastReceiverOptions
中设置 touchScreenOptimizedApp
。在此 Codelab 中,我们使用的是 <cast-media-player> 元素。
context.start({ touchScreenOptimizedApp: true });
系统根据 MetadataType
和 MediaStatus.supportedMediaCommands
为每个槽位分配默认控件按钮。
视频控件
对于 MetadataType.MOVIE
、MetadataType.TV_SHOW
和 MetadataType.GENERIC
,智能显示屏的界面控件对象将如下所示。
--playback-logo-image
MediaMetadata.subtitle
MediaMetadata.title
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
音频控制
对于 MetadataType.MUSIC_TRACK
,智能显示屏的界面控件对象将如下所示:
--playback-logo-image
MusicTrackMediaMetadata.albumName
MusicTrackMediaMetadata.title
MusicTrackMediaMetadata.albumArtist
MusicTrackMediaMetadata.images[0]
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
更新支持的媒体命令
界面控件对象还会根据 MediaStatus.supportedMediaCommands
确定是否显示 ControlsButton
。
当 supportedMediaCommands
的值等于 ALL_BASIC_MEDIA
时,默认控件布局将如下所示:
当 supportedMediaCommands
的值等于 ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
时,默认控件布局将如下所示:
当 supportedMediaCommands 的值等于 PAUSE | QUEUE_PREV | QUEUE_NEXT
时,默认控件布局将如下所示:
如果有文字轨道,字幕按钮将始终显示在 SLOT_1
处。
如需在启动接收器上下文后动态更改 supportedMediaCommands
的值,您可以调用 PlayerManager.setSupportedMediaCommands
来替换该值。此外,您还可以使用 addSupportedMediaCommands
添加新命令,或使用 removeSupportedMediaCommands
移除现有命令。
自定义控件按钮
您可以使用 PlayerDataBinder
自定义控件。将以下代码添加到 js/receiver.js
文件中的 touchControls 下方,以设置控件的第一个槽:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
// Clear default buttons and re-assign
touchControls.clearDefaultSlotAssignments();
touchControls.assignButton(
cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
);
});
context.start();
11. 在智能显示屏上实现媒体浏览
媒体浏览是一项 CAF 接收器功能,可让用户在触摸设备上探索更多内容。为了实现这一点,您将使用 PlayerDataBinder
设置 BrowseContent
界面。然后,您可以根据要显示的内容使用 BrowseItems
进行填充。
BrowseContent
以下是 BrowseContent
界面及其属性的示例:
BrowseContent.title
BrowseContent.items
宽高比
您可以使用targetAspectRatio property
为图片素材资源选择最佳宽高比。CAF 接收器 SDK 支持三种宽高比:SQUARE_1_TO_1
、PORTRAIT_2_TO_3
、LANDSCAPE_16_TO_9
。
BrowseItem
使用 BrowseItem
显示每一项的标题、副标题、时长和图片:
BrowseItem.image
BrowseItem.duration
BrowseItem.title
BrowseItem.subtitle
设置媒体浏览数据
您可以通过调用 setBrowseContent
提供可供浏览的媒体内容列表。将以下代码添加到 js/receiver.js
文件中的 playerDataBinder
下方和 MEDIA_CHANGED
事件监听器中,以设置标题为“Up Next”的浏览项。
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
...
let browseItems = getBrowseItems();
function getBrowseItems() {
let browseItems = [];
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
for (let key in data) {
let item = new cast.framework.ui.BrowseItem();
item.entity = key;
item.title = data[key].title;
item.subtitle = data[key].description;
item.image = new cast.framework.messages.Image(data[key].poster);
item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
browseItems.push(item);
}
});
return browseItems;
}
let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
....
// Media browse
touchControls.setBrowseContent(browseContent);
});
点击媒体浏览项会触发 LOAD
拦截器。将以下代码添加到 LOAD
拦截器,以将 request.media.contentId
映射到媒体浏览项中的 request.media.entity
:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
...
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
...
});
});
您还可以将 BrowseContent
对象设置为 null
以移除媒体浏览界面。
12. 调试接收器应用
Cast 接收器 SDK 为开发者提供了另一种选择,让他们可以使用 CastDebugLogger API 和配套的命令和控制 (CaC) 工具获取日志,从而轻松调试接收器应用。
初始化
如需集成 API,请在 index.html 文件中添加 CastDebugLogger
源脚本。应在 Cast 接收器 SDK 声明后的 <head> 标记中声明来源。
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<!-- Cast Debug Logger -->
<script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>
在文件顶部的 js/receiver.js
和 playerManager
下方,添加以下代码以检索 CastDebugLogger
实例并启用日志记录器:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
启用调试记录器后,接收器上会显示一个叠加层,上面显示 DEBUG MODE
。
记录播放器事件
使用 CastDebugLogger
,您可以轻松记录由 CAF 接收器 SDK 触发的播放器事件,并使用不同的日志记录器级别来记录事件数据。loggerLevelByEvents
配置使用 cast.framework.events.EventType
和 cast.framework.events.category
指定要记录的事件。
在 castDebugLogger
声明下方添加以下代码,以便在触发了播放器 CORE
事件或广播 mediaStatus
更改时进行记录:
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
日志消息和自定义标记
借助 CastDebugLogger API,您可以创建日志消息,这些消息会以不同的颜色显示在接收器的调试叠加层上。您可以使用以下日志方法,这些方法按照优先级从高到低的顺序列示:
castDebugLogger.error(custom_tag, message);
castDebugLogger.warn(custom_tag, message);
castDebugLogger.info(custom_tag, message);
castDebugLogger.debug(custom_tag, message);
对于每种日志方法,第一个参数都是一个自定义标记。这可以是您认为有意义的任何标识字符串。CastDebugLogger
使用标记来过滤日志。下面将详细介绍标记的用法。第二个参数是日志消息。
如需显示日志的实际效果,请将日志添加到 LOAD
拦截器中。
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
castDebugLogger.error(LOG_TAG, 'Content not found');
reject();
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);
// Add metadata
let metadata = new cast.framework.messages.MovieMediaMetadata();
metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
您可以在 loggerLevelByTags
中为每个自定义标记设置日志级别,从而控制在调试叠加层中显示哪些���息。例如,启用日志级别为 cast.framework.LoggerLevel.DEBUG
的自定义标记将显示添加的所有消息,包括错误、警告、信息和调试日志消息。启用级别为 WARNING
的自定义标记将仅显示错误和警告日志消息。
loggerLevelByTags
配置是可选的。如果没有为其日志记录器级别配置自定义标记,则所有日志消息都会显示在调试叠加层上。
在 CORE
事件记录器下方添加以下代码:
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
[LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};
调试叠加层
Cast 调试记录器在接收器上提供了一个叠加式调试界面,用于在投射设备上显示您的自定义日志消息。使用 showDebugLogs
切换调试叠加层,使用 clearDebugLogs
清除叠加层上的日志消息。
添加以下代码,在接收器上预览调试叠加层。
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Show debug overlay
castDebugLogger.showDebugLogs(true);
// Clear log messages on debug overlay
castDebugLogger.clearDebugLogs();
}
});
13. 恭喜
您现在已经知道如何使用 Cast Web 接收器 SDK 创建自定义网页接收器应用。
如需了解详情,请参阅网络接收器开发者指南。