播放透過 Google Cloud Video Stitcher API 註冊的 VOD 串流
本指南說明如何使用 CAF Web Receivers 適用的 IMA DAI SDK,要求及播放 Google Cloud VOD 串流工作階段。
本指南會擴充全服務 DAI 的基本範例,新增對透過 Google Cloud Video Stitcher API 註冊的串流支援。
請先確認 CAF 網頁接收器支援你的串流格式,再繼續操作。
如要瞭解如何與其他平台整合,或使用 IMA 用戶端 SDK,請參閱「互動式媒體廣告 SDK」。
背景
使用本指南前,請先熟悉 Chromecast 應用程式架構的網頁接收器通訊協定。
本指南假設您已基本熟悉 CAF 接收器概念,例如訊息攔截器、MediaInformation 物件,以及使用 Cast Command and Control 工具模擬 CAF 傳送器。
應用程式元件和架構
使用 IMA CAF DAI SDK 實作 VOD 串流播放功能時,需要用到 Google Cloud Video Stitcher API,並包含兩個主要元件,如本指南所示:
VideoStitcherVodStreamRequest:定義向 Google 伺服器發出的串流要求的物件。StreamManager: 這個物件會處理影片串流和 IMA DAI SDK 之間的通訊,例如觸發追蹤 Ping 和將串流事件轉送給發布商。
設定 Google Cloud 專案
輸入下列變數,供 IMA SDK 使用:
位置:建立 VOD 設定的 Google Cloud 區域。
LOCATION專案編號:使用 Video Stitcher API 的 Google Cloud 專案編號。
PROJECT_NUMBEROAuth 權杖:服務帳戶的短期 OAuth 權杖,具有 Video Stitcher 使用者角色。進一步瞭解如何為服務帳戶建立短期憑證。
OAUTH_TOKENNetwork Code:用於要求廣告的 Google Ad Manager 聯播網代碼。
NETWORK_CODEVOD 設定 ID - VOD 串流的 VOD 設定 ID。
VOD_CONFIG_ID如要進一步瞭解如何建立 VOD 設定 ID,請參閱「Cloud 縫合建立 VOD 設定指南」。
VOD_URI
設定自訂投放接收端
如要開發自訂 Cast 接收器,請備妥下列項目:
已將測試裝置加入允許清單的 Cast 開發人員控制台帳戶。
已向 Cast 開發人員控制台註冊的代管網頁接收器應用程式,且可修改為代管本指南提供的程式碼。
已設定使用網頁接收器應用程式的傳送端應用程式。在本範例中,本指南會使用 Cast Command and Control 工具做為傳送端。
準備傳送者,將串流資料傳遞給接收者
首先,請設定傳送端應用程式,向網路接收器發出載入要求,並在平台 MediaInformation 物件中包含下列欄位。
| 欄位 | 目錄 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
contentId
|
這個媒體項目的專屬 ID,如 Cast 參考文件中所定義。請勿在同一個媒體佇列中,將這個 ID 重複用於多個項目。
|
||||||||||||
contentUrl
|
如果動態廣告插播串流無法載入,系統會播放選用的備份串流 URL。
|
||||||||||||
contentType
|
如果 DAI 串流無法載入,系統會播放備份串流 URL (選用)。
|
||||||||||||
streamType
|
用於這個值的字串常值或常數,會因傳送者平台而異。
|
||||||||||||
customData
|
|
以下提供幾個程式碼範例,協助您順利上手:
網頁
如要在 Cast 網頁傳送器中設定這些值,請先使用必要資料建立 MediaInfo 物件,然後向網頁接收器發出 load 要求。
// 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 網頁傳送器中設定這些值,請先使用必要資料建立 MediaInfo 物件,然後向網頁接收器發出 load 要求。
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 網頁傳送器中設定這些值,請先使用必要資料建立 GCKMediaInformation 物件,然後向網頁接收器發出 load 要求。
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 網頁傳送器中設定這些值,請先使用必要資料建立 GCKMediaInformation 物件,然後向網頁接收器發出 load 要求。
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
}
獲客成本工具
如要在 Cast Command and Control 工具中設定這些值,請按一下「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 網頁接收器
建立自訂網頁接收器,如 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>
const castContext = cast.framework.CastReceiverContext.getInstance()
castContext.start();
</script>
</body>
</html>
匯入 IMA DAI SDK 並取得 Player Manager
在載入 CAF 的指令碼之後,將指令碼標記新增至網頁接收器,匯入 CAF 適用的 IMA DAI SDK。接著,在後續的指令碼標記中,將接收器內容和播放器管理工具儲存為常數,然後啟動接收器。
<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 Stream Manager
初始化 IMA Stream Manager。
<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);