选择您感兴趣的 DAI 解决方案
广告连播投放 DAI
IMA SDK 可简化将多媒体广告集成到网站和应用中的过程。
IMA SDK 可以从任何与 VAST 兼容的广告服务器请求广告,并管理应用中的广告播放。
借助 IMA DAI SDK,应用可以针对 VOD 或直播内容发出广告和内容视频的流式传输请求。然后,SDK 会返回组合的视频流, 让您不必管理在应用程序内的广告和内容视频之间的切换 应用。
本指南将演示如何使用 IMA DAI SDK for CAF。
在使用本指南之前,请先熟悉 Chromecast 应用框架的 Web 接收器协议。本指南假定您对 CAF 接收器概念(例如消息拦截器和 mediaInformation 对象)有基本的了解,并且熟悉如何使用 Cast 命令和控制工具来模拟 CAF 发送器。
要使用 IMA DAI 广告连播投放,您必须与广告连播投放合作伙伴合作 必须具有 Ad Manager 360 高级课程 。如果您有 Ad Manager 账号,请联系您的客户经理 。有关注册 Ad Manager 的信息,请访问 Ad Manager 帮助中心。
有关与其他平台集成或使用 IMA 客户端 SDK,请参阅互动式媒体广告 SDK。
IMA DAI Pod Serving 概览
使用 IMA CAF DAI SDK 实施广告连播投放涉及两个主要组件: 具体说明如下:
StreamRequest
: 用于定义向 Google 广告服务器的视频流请求的对象。 请求中会指定广告联盟代码、自定义素材资源键和可选 API 密钥,以及其他可选参数。StreamManager
: 用于处理视频流与 IMA DAI 之间的通信的对象 例如触发跟踪 ping,以及将视频流事件转发到 发布商。
前提条件
- 一个已注册测试设备的 Cast Developer Console 账号。
- 已在 Cast 开发者控制台中注册的托管网络接收器应用,可修改为托管本指南提供的代码。
- 配置为使用您的网页接收器应用的发送应用。对于 在此示例中,请使用 Cast 命令和控件 工具作为您的发件人。
配置发件人的 MediaInfo 对象
首先,配置发件人应用的 MediaInfo
对象,使其包含以下字段:
字段 | 目录 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
contentId
|
此媒体内容的唯一标识符。
CONTENT_ID |
||||||||||
contentUrl
|
可选。如果 DAI 直播无法加载,则要播放的备用直播网址。
BACKUP_STREAM_URL |
||||||||||
contentType
|
可选。内容备份串流的 MIME 类型。仅 DASH 需要
数据流。
CONTENT_STREAM_MIMETYPE |
||||||||||
streamType
|
用于此值的字符串字面量或常量因发件人而异 平台。 | ||||||||||
customData
|
customData 字段包含其他必填字段的键值对存储区。在此示例中,它包含您的 DAI 视频流参数。在
您可以改为传递
接收器应用将使用服务器端检索这些参数
请求。
|
以下是一些可帮助您上手的代码示例:
Web
如需在 Cast Web 发送器中配置这些值,请先创建包含所需数据的 MediaInfo
对象,然后向 Web 接收器发出加载请求。
// Create mediaInfo object
const mediaInfo = new chrome.cast.media.MediaInfo("CONTENT_ID");
mediaInfo.contentUrl = "BACKUP_STREAM_URL";
mediaInfo.contentType = "CONTENT_STREAM_MIMETYPE";
mediaInfo.streamType = chrome.cast.media.StreamType.LIVE;
mediaInfo.customData = {
daiStreamType: "DAI_STREAM_TYPE",
networkCode: "NETWORK-CODE",
customAssetKey: "CUSTOM_ASSET_KEY",
apiKey: "API_KEY"
};
// 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 网络发送器中配置这些值,请先创建一个 MediaInfo 对象 然后生成 向网页加载请求 接收器。
JSONObject customData = new JSONObject()?
.put("daiStreamType", "DAI_STREAM_TYPE")
.put("networkCode", "NETWORK-CODE")
.put("customAssetKey", "CUSTOM_ASSET_KEY")
.put("apiKey", "API_KEY");
MediaInfo mediaInfo = MediaInfo.Builder("CONTENT_ID")
.setContentUrl("BACKUP_STREAM_URL")
.setContentType("CONTENT_STREAM_MIMETYPE")
.setStreamType(MediaInfo.STREAM_TYPE_LIVE)
.setCustomData(customData)
.build();
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());
iOS (Obj-C)
要在 Cast 网络发送器中配置这些值,请先创建一个
GCKMediaInformation
对象,然后进行加载
请求发送给网络接收器。
NSURL url = [NSURL URLWithString:@"BACKUP_STREAM_URL"];
NSDictionary *customData = @{
@"daiStreamType": @"DAI_STREAM_TYPE",
@"networkCode": @"NETWORK-CODE",
@"customAssetKey": @"CUSTOM_ASSET_KEY",
@"apiKey": @"API_KEY"};
mediaInfoBuilder.customData = customData;
GCKMediaInformationBuilder *mediaInfoBuilder =
[[GCKMediaInformationBuilder alloc] initWithContentID: @"CONTENT_ID"];
mediaInfoBuilder.contentURL = url;
mediaInfoBuilder.contentType = @"CONTENT_STREAM_MIMETYPE";
mediaInfoBuilder.streamType = GCKMediaStreamTypeLive;
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 = [
"daiStreamType": "DAI_STREAM_TYPE",
"networkCode": "NETWORK-CODE",
"customAssetKey": "CUSTOM_ASSET_KEY",
"region": "API_KEY"
]
let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentId: "CONTENT_ID")
mediaInfoBuilder.contentURL = mediaUrl
mediaInfoBuilder.contentType = @"CONTENT_STREAM_MIMETYPE"
mediaInfoBuilder.streamType = GCKMediaStreamType.Live
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”。然后,将文本区域中的 JSON 数据替换为以下 JSON:
{
"media": {
"contentId": "CONTENT_ID",
"contentUrl": "BACKUP_STREAM_URL",
"contentType": ""CONTENT_STREAM_MIMETYPE"",
"streamType": "LIVE",
"customData": {
"daiStreamType": "DAI_STREAM_TYPE",
"networkCode": "NETWORK-CODE",
"customAssetKey": "CUSTOM_ASSET_KEY",
"oAuthToken": "API_KEY"
}
}
}
此自定义加载请求可发送给接收器,以测试其余步骤。
创建基本 CAF 接收器
创建自定义网络接收器,如 CAF SDK 自定义网络接收器中所示 导视面板。
接收器的代码应如下所示:
<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>
// ...
</script>
</body>
</html>
导入 IMA DAI SDK 并获取 Player Manager
添加脚本代码,将适用于 CAF 的 IMA DAI SDK 导入您的网页接收器, 在脚本加载 CAF 之后。在脚本标记中,在启动接收器之前,将接收器上下文和播放器管理器存储为常量。
<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 livestream request object for a pod serving stream.
* @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((castRequestWithPodStreamData) => {
console.log('Successfully made DAI stream request.');
// ...
return castRequestWithPodStreamData;
})
.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 加载请求创建 pod 服务流。
/**
* Creates a livestream request object for a pod serving stream.
* @param {!LoadRequestData} castRequest The request object from the cast sender
* @return {StreamRequest} an IMA stream request
*/
const createStreamRequest = (castRequest) => {
const customData = castRequest.media.customData;
let streamRequest;
if (customData.daiStreamType == "LIVE") {
streamRequest = new google.ima.cast.dai.api.PodStreamRequest();
streamRequest.customAssetKey = customData.customAssetKey;
streamRequest.networkCode = customData.networkCode;
streamRequest.apiKey = customData.apiKey;
} else if (customData.daiStreamType == "VOD") {
streamRequest = new google.ima.cast.dai.api.PodVodStreamRequest();
streamRequest.networkCode = customData.networkCode;
streamRequest.apiKey = customData.apiKey;
}
return streamRequest;
};
从 VTP 检索拼接的清单
如果您的数据流请求成功,请使用 streamManager.getStreamId()
检索数据流的 ID。您的视频技术合作伙伴 (VTP) 或自定义清单
操作器将使用
数据流 ID。
检索到清单网址后,替换现有的 contentUrl
新的 manifestUrl
。
最后,在返回经过修改的直播清单之前,请对 streamManager
调用 loadStreamMetadata
方法,以告知 IMA SDK 可以安全地请求直播元数据。这场通话
仅在 VOD 视频流中可用。
/**
* 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((castRequestWithPodStreamData) => {
console.log('Successfully made DAI stream request.');
// This is a sample VTP integration. Consult your VTP documentation
// for how to retrieve an ad-stitched stream manifest URL.
const manifestTemplate = "https://.../manifest.m3u8?gam_stream_id=[[STREAMID]]";
const streamId = streamManager.getStreamId();
const manifestUrl = manifestTemplate.replace('[[STREAMID]]', streamId)
// Assign your manifestUrl to the request's content URL.
castRequestWithPodStreamData.media.contentUrl = manifestUrl;
// After generating the manifest URL, VOD streams must notify the
// IMA SDK that it is safe to request ad pod metadata.
// This is only necessary for VOD streams. It is a no-op for
// livestreams, so no conditional is needed.
streamManager.loadStreamMetadata();
return castRequestWithPodStreamData;
})
.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;
});
};
现在,您可以使用 Cast 应用框架和适用于 CAF 的 IMA DAI SDK 请求和播放 pod 广告投放流式传输。