播放使用 Google Cloud Video Stitcher API 注册的 VOD 串流
本指南演示了如何使用适用于 CAF Web 接收器的 IMA DAI SDK 请求和播放 Google Cloud VOD 流式传输会话。
本指南对完整服务 DAI 的基本示例进行了扩展,添加了对使用 Google Cloud Video Stitcher API 注册的串流的支持。
请先确保 CAF Web 接收器支持您的在线播放格式,然后再继续。
如需了解如何与其他平台集成或如何使用 IMA 客户端 SDK,请参阅互动式媒体广告 SDK。
背景
在使用本指南之前,请先熟悉 Chromecast 应用框架的 Web 接收器协议。
本指南假定您基本熟悉 CAF 接收器概念,例如消息拦截器、MediaInformation
对象,以及使用 Cast 命令和控制工具来模拟 CAF 发送器。
应用组件和架构
如本指南所示,使用 Google Cloud Video Stitcher API 和 IMA CAF DAI SDK 实现 VOD 流式播放涉及两个主要组成部分:
VideoStitcherVodStreamRequest
:用于定义对 Google 服务器的流式传输请求的对象。StreamManager
:用于处理视频流与 IMA DAI SDK 之间的通信的对象,例如触发跟踪 ping 和将流事件转发给发布商。
设置 Google Cloud 项目
输入以下变量以在 IMA SDK 中使用:
位置 - 创建 VOD 配置的 Google Cloud 区域。
LOCATION
Project Number:使用 Video Stitcher API 的 Google Cloud 项目编号。
PROJECT_NUMBER
OAuth 令牌:服务账号的短期有效 OAuth 令牌,具有视频剪辑器用户角色。详细了解如何为服务账号创建短期凭据。
OAUTH_TOKEN
广告资源网代码:用于请求广告的 Google Ad Manager 广告资源网代码。
NETWORK_CODE
VOD 配置 ID - VOD 视频流的 VOD 配置 ID。
VOD_CONFIG_ID
如需详细了解如何创建 VOD 配置 ID,请参阅 Cloud 拼接创建 VOD 配置指南。
VOD_URI
设置自定义投屏接收器
如需开发自定义投放接收器,您需要满足以下条件:
一个 Cast 开发者控制台账号,其中包含已列入许可名单的测试设备。
已在 Cast 开发者控制台中注册的托管网络接收器应用,可修改为托管本指南提供的代码。
已配置为使用 Web 接收器应用的发送应用。在本例中,本指南使用 Cast 命令和控制工具作为发送方。
准备好发送端以将流数据传递给接收端
首先,将发送方应用配置为向 Web 接收器发出加载请求,并在平台的 MediaInformation
对象中包含以下字段。
字段 | 目录 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
contentId
|
此媒体内容的唯一标识符,如投放参考文档中所定义。请勿将此 ID 重复用于同一媒体队列中的多个项。
|
||||||||||||
contentUrl
|
备用直播网址(可选),用于在 DAI 直播无法加载时播放。
|
||||||||||||
contentType
|
备用视频流网址的 MIME 类型(可选),用于在 DAI 视频流无法加载时播放。
|
||||||||||||
streamType
|
用于此值的字符串字面量或常量因发件人平台而异。
|
||||||||||||
customData
|
|
以下是一些代码示例,可帮助您开始使用:
Web
如需在 Cast Web 发送器中配置这些值,请先创建包含所需数据的 MediaInfo
对象,然后向 Web 接收器发出加载请求。
// Create mediaInfo object
const mediaInfo = new chrome.cast.media.MediaInfo("CONTENT_ID");
mediaInfo.contentUrl = "BACKUP_STREAM_URL";
mediaInfo.contentType = "BACKUP_STREAM_MIMETYPE";
mediaInfo.streamType = chrome.cast.media.StreamType.VOD;
mediaInfo.customData = {
region: "LOCATION",
projectNumber: "PROJECT_NUMBER",
oAuthToken: "OAUTH_TOKEN",
networkCode: "NETWORK_CODE",
vodConfigId: "VOD_CONFIG_ID"
};
// 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 Web 发送器中配置这些值,请先使用所需数据创建 MediaInfo
对象,然后向 Web 接收器发出加载请求。
JSONObject customData = new JSONObject()
.put("region", "LOCATION")
.put("projectNumber", "PROJECT_NUMBER")
.put("oAuthToken", "OAUTH_TOKEN")
.put("networkCode", "NETWORK_CODE")
.put("vodConfigId", "VOD_CONFIG_ID");
MediaInfo mediaInfo = MediaInfo.Builder("CONTENT_ID")
.setContentUrl("BACKUP_STREAM_URL")
.setContentType("BACKUP_STREAM_MIMETYPE")
.setStreamType(MediaInfo.STREAM_TYPE_VOD)
.setCustomData(customData)
.build();
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());
iOS (Obj-C)
如需在 Cast Web 发送器中配置这些值,请先创建包含所需数据的 GCKMediaInformation
对象,然后向 Web 接收器发出加载请求。
NSURL url = [NSURL URLWithString:@"BACKUP_STREAM_URL"];
NSDictionary *customData = @{
@"region": @"LOCATION",
@"projectNumber": @"PROJECT_NUMBER",
@"oAuthToken": @"OAUTH_TOKEN",
@"networkCode": @"NETWORK_CODE",
@"vodConfigId": @"VOD_CONFIG_ID"
};
GCKMediaInformationBuilder *mediaInfoBuilder =
[[GCKMediaInformationBuilder alloc] initWithContentID: @"CONTENT_ID"];
mediaInfoBuilder.contentURL = url;
mediaInfoBuilder.contentType = @"BACKUP_STREAM_MIMETYPE";
mediaInfoBuilder.streamType = GCKMediaStreamTypeNone;
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 Web 发送器中配置这些值,请先创建包含所需数据的 GCKMediaInformation
对象,然后向 Web 接收器发出加载请求。
let url = URL.init(string: "BACKUP_STREAM_URL")
guard let mediaURL = url else {
print("invalid mediaURL")
return
}
let customData = [
"region": "LOCATION",
"projectNumber": "PROJECT_NUMBER",
"oAuthToken": "OAUTH_TOKEN",
"networkCode": "NETWORK_CODE",
"vodConfigId": "VOD_CONFIG_ID"
]
let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentId: "CONTENT_ID")
mediaInfoBuilder.contentURL = mediaUrl
mediaInfoBuilder.contentType = "BACKUP_STREAM_MIMETYPE"
mediaInfoBuilder.streamType = GCKMediaStreamType.none
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 命令和控制工具中配置这些值,请点击“Load Media”(加载媒体)标签页,然后将自定义加载请求类型设置为“LOAD”。然后,将文本区域中的 JSON 数据替换为以下 JSON:
{
"media": {
"contentId": "CONTENT_ID",
"contentUrl": "BACKUP_STREAM_URL",
"contentType": "BACKUP_STREAM_MIMETYPE",
"streamType": "VOD",
"customData": {
"region": "LOCATION",
"projectNumber": "PROJECT_NUMBER",
"oAuthToken": "OAUTH_TOKEN",
"networkCode": "NETWORK_CODE",
"vodConfigId": "VOD_CONFIG_ID"
}
}
}
此自定义加载请求可发送给接收器,以测试其余步骤。
创建自定义 CAF Web 接收器
创建自定义 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>
const castContext = cast.framework.CastReceiverContext.getInstance()
castContext.start();
</script>
</body>
</html>
导入 IMA DAI SDK 并获取 Player Manager
在脚本加载 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 串流管理器。
<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>
创建 Stream Manager 加载拦截器
在媒体内容传递给 CAF 之前,请在 LOAD 消息拦截器中创建流式传输请求。
const castContext = cast.framework.CastReceiverContext.getInstance();
const playerManager = castContext.getPlayerManager();
const streamManager = new google.ima.cast.dai.api.StreamManager();
/**
* Creates a VOD stream request object for the Video Stitcher API.
* @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((castRequestWithStreamData) => {
console.log('Successfully made DAI stream request.');
return castRequestWithStreamData;
})
.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 加载请求创建 Video Stitcher API VOD 串流请求。
/**
* Creates a VOD stream request object for the Video Stitcher API.
* @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.VideoStitcherVodStreamRequest();
const customData = castRequest.media.customData;
streamRequest.region = customData.region;
streamRequest.projectNumber = customData.projectNumber;
streamRequest.oAuthToken = customData.oAuthToken;
streamRequest.networkCode = customData.networkCode;
streamRequest.vodConfigId = customData.vodConfigId;
streamRequest.videoStitcherSessionOptions = {};
return streamRequest;
};
(可选)添加在线播放会话选项
使用 VideoStitcherVodStreamRequest.videoStitcherSessionOptions
添加会话选项以替换默认的 Cloud Video Stitcher API 配置,从而自定义您的串流请求。
如果您提供的选项无法识别,Cloud Video Stitcher API 将返回 HTTP 400 错误。如需帮助,请参阅问题排查指南。
例如,您可以使用以下代码段替换清单选项,该代码段会请求两个串流清单,其中呈现方式的排序方式为从最低比特率到最高比特率。
...
// The following session options are examples. Use session options
// that are compatible with your video stream.
streamRequest.videoStitcherSessionOptions = {
"manifestOptions": {
"bitrateOrder": "ascending"
}
};
streamManager.requestStream(streamRequest);