IMA SDK 可讓您輕鬆將多媒體廣告整合至您的網站和應用程式。IMA SDK 可向任何符合 VAST 規定的廣告伺服器要求廣告,並管理應用程式中的廣告播放作業。使用 IMA DAI SDK 時,應用程式可提供 廣告和內容影片的串流請求 (VOD 或直播內容)。接著,SDK 會傳回合併的影片串流,因此您不必在應用程式中管理廣告和內容影片之間的切換。
選取感興趣的動態廣告解決方案
廣告連播放送 DAI
本指南說明如何播放直播或 VOD 的 DAI 廣告連播放送串流 使用 IMA DAI SDK for HTML5,並搭配採用 hls.js 的影片播放器 以便播放。如果您要檢視或繼續完成樣本 整合,並支援 HLS.js 和 Safari 播放,請參閱 HLS 廣告連播放送範例。 如需 DASH.js 支援資訊,請參閱 DASH 容器服務範例。您可以從 HTML5 DAI GitHub 版本下載這些範例應用程式 頁面。
DAI 廣告連播放送功能總覽
使用 IMA DAI SDK 導入廣告連播放送時需要兩個主要元件: 指南要素:
PodStreamRequest
/PodVodStreamRequest
:定義傳送至 Google 廣告伺服器的串流要求的物件。要求會指定 Network Code,而PodStreamRequest
也需要 Custom Asset Key,以及選用的 API 金鑰。兩者都含有其他選用參數。StreamManager
:這個物件會處理 影片和 IMA DAI SDK 相關,例如觸發追蹤連線偵測 (ping) 和 將串流事件轉送至發布商。
必要條件
開始之前,請先準備下列項目:
三個空白檔案:
- dai.html
- dai.css
- dai.js
安裝在電腦上的 Python,或者網路伺服器或其他代管的開發 測試環境
設定開發環境
由於 SDK 會使用與載入頁面相同的通訊協定載入依附元件,因此您需要使用網路伺服器來測試應用程式。如要快速啟動本機開發伺服器,請使用 Python 內建的伺服器。
使用指令列,從含有
index.html
檔案的目錄執行:python -m http.server 8000
透過網路瀏覽器前往
http://localhost:8000/
您也可以使用任何其他代管開發環境或網路伺服器,例如 Apache HTTP Server。
建立簡單的影片播放器
首先,修改 dai.html 以建立簡單的 HTML5 影片元素,並將 div 改為
用於廣告 UI 元素另加入必要代碼以載入 dai.css
和 dai.js 檔案,以及匯入 hls.js
影片播放器。
接著,修改 dai.css,指定網頁元素的大小和位置。
最後,在 dai.js 中定義變數,以便保存串流要求資訊,以及在網頁載入時執行的 initPlayer()
函式。
串流要求常數如下:
BACKUP_STREAM
:如果廣告處理程序發生致命錯誤,則會播放備用串流的網址。STREAM_URL
:僅適用於直播。由供應商提供的影片串流網址 來管理資訊清單操作員或第三方合作夥伴。它應該 您必須先插入 IMA DAI SDK 提供的串流 ID,才能 提出要求。在這個例子中,串流網址會包含預留位置[[STREAMID]]
。在發出要求前會替換為串流 ID。NETWORK_CODE
:Ad Manager 360 帳戶的聯播網代碼。CUSTOM_ASSET_KEY
:僅適用於直播。自訂素材資源金鑰 在 Ad Manager 360 中識別廣告連播放送事件建立 Deployment 的 資訊清單操縱器或第三方 Pod 放送合作夥伴API_KEY
:僅適用於直播。可選的 API 金鑰,可能需要用於從 IMA DAI SDK 擷取串流 ID。
dai.html
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="dai.js"></script>
<link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
<h2>IMA DAI SDK Demo (HLS.JS)</h2>
<video id="video"></video>
<div id="ad-ui"></div>
</body>
</html>
dai.css
#video,
#ad-ui {
width: 640px;
height: 360px;
position: absolute;
top: 35px;
left: 0;
}
#ad-ui {
cursor: pointer;
}
dai.js
var BACKUP_STREAM =
'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'
// Stream Config.
const STREAM_URL = "https://encodersim.sandbox.google.com/masterPlaylist/...&stream_id=[[STREAMID]]";
const NETWORK_CODE = "51636543";
const CUSTOM_ASSET_KEY = "google-sample";
const API_KEY = "";
var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
}
載入 IMA DAI SDK
接著,使用 dai.html 中的指令碼代碼,在代碼前方加入 DAI 架構 dai.js。
dai.html
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
<script src="dai.js"></script>
<link rel="stylesheet" href="dai.css" type="text/css">
</head>
...
初始化 StreamManager 並提出直播或隨選串流要求
直播廣告連播放送
如要要求一組廣告,請建立 ima.dai.api.StreamManager
,負責要求及管理 DAI 串流。建構函式會採用影片元素,而產生的例項會採用廣告 UI 元素來處理廣告互動。
接著,定義函式來要求 Pod 服務直播。這個函式
先建立 PodStreamRequest
,並使用 streamRequest 進行設定
再呼叫 streamManager.requestStream()
對應到該要求物件
dai.js
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)
requestLivePodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}
function requestLivePodStream(networkCode, customAssetKey, apiKey) {
// clear HLS.js instance, if in use
if (hls) {
hls.destroy();
}
// Generate a Pod Serving live Stream Request
const streamRequest = new google.ima.dai.api.PodStreamRequest();
streamRequest.networkCode = networkCode;
streamRequest.customAssetKey = customAssetKey;
streamRequest.apiKey = apiKey;
streamRequest.format = 'hls';
streamManager.requestStream(streamRequest);
}
VOD 廣告連播放送
如要要求一組廣告,請建立 ima.dai.api.StreamManager
,負責要求及管理 DAI 串流。建構函式會擷取
影片元素,而產生的執行個體會使用廣告 UI 元素來處理廣告
互動情形
接著,請定義一個函式,要求 Pod 提供 VOD 串流。這個函式
先建立 PodVodStreamRequest
,並使用 streamRequest 進行設定
再呼叫 streamManager.requestStream()
對應到該要求物件
dai.js
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)
requestVodPodStream(NETWORK_CODE);
}
function requestVodPodStream(networkCode) {
// clear HLS.js instance, if in use
if (hls) {
hls.destroy();
}
// Generate a Pod Serving VOD Stream Request
const streamRequest = new google.ima.dai.api.PodVodStreamRequest();
streamRequest.networkCode = networkCode;
streamRequest.format = 'hls';
streamManager.requestStream(streamRequest);
}
處理串流事件
直播廣告連播放送
接下來,實作主要影片事件的事件監聽器。這個範例會呼叫 onStreamEvent()
函式,處理 STREAM_INITIALIZED
、ERROR
、AD_BREAK_STARTED
和 AD_BREAK_ENDED
事件。這個函式可處理串流
以及在廣告播放期間停用播放器控制項
都必須發出 SDK 才能使用載入串流時,影片播放器會使用 loadStream()
函式載入並播放提供的網址。
dai.js
var isAdBreak;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
streamManager.addEventListener(
[google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
google.ima.dai.api.StreamEvent.Type.ERROR,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
onStreamEvent,
false);
...
function onStreamEvent(e) {
switch (e.type) {
case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
console.log('Stream initialized');
loadStream(e.getStreamData().streamId);
break;
case google.ima.dai.api.StreamEvent.Type.ERROR:
console.log('Error loading stream, playing backup stream.' + e);
loadStream('');
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
console.log('Ad Break Started');
isAdBreak = true;
videoElement.controls = false;
adUiElement.style.display = 'block';
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
console.log('Ad Break Ended');
isAdBreak = false;
videoElement.controls = true;
adUiElement.style.display = 'none';
break;
default:
break;
}
}
function loadStream(streamID) {
var url;
if(streamID) {
url = STREAM_URL.replace('[[STREAMID]]', streamID);
} else {
console.log('Stream Initialization Failed');
url = BACKUP_STREAM;
}
console.log('Loading:' + url);
hls.loadSource(url);
hls.attachMedia(videoElement);
}
VOD 廣告連播放送
接著,為主要影片事件實作事件監聽器。這個範例控制站
STREAM_INITIALIZED
、LOADED
、ERROR
、AD_BREAK_STARTED
和
呼叫 onStreamEvent()
函式來取得 AD_BREAK_ENDED
事件。這個
函式會處理串流的載入和錯誤,以及停用播放器
控制項,因為 SDK 需要使用控制項。
此外,VOD 小組供應串流需要呼叫 StreamManager.loadStreamMetadata()
,以回應 STREAM_INITIALIZED
事件。您也必須向影片技術合作夥伴 (VTP) 索取串流網址。loadStreamMetadata()
呼叫成功後,系統會觸發 LOADED
事件,您應使用串流網址呼叫 loadStream()
函式,以便載入及播放串流。
var isAdBreak;
function initPlayer() {
videoElement = document.getElementById('video');
adUiElement = document.getElementById('adUi');
streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
streamManager.addEventListener(
[google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
google.ima.dai.api.StreamEvent.Type.ERROR,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
onStreamEvent,
false);
...
function onStreamEvent(e) {
switch (e.type) {
case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
const streamId = e.getStreamData().streamId;
// 'vtpInterface' is a place holder for your own video technology
// partner (VTP) API calls.
vtpInterface.requestStreamURL({
'streamId': streamId,
})
.then( (vtpStreamUrl) => {
streamUrl = vtpStreamUrl;
streamManager.loadStreamMetadata();
}, (error) => {
// Handle the error.
});
break;
case google.ima.dai.api.StreamEvent.Type.LOADED:
loadStream(streamUrl);
break;
case google.ima.dai.api.StreamEvent.Type.ERROR:
console.log('Error loading stream, playing backup stream.' + e);
loadStream();
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
console.log('Ad Break Started');
isAdBreak = true;
videoElement.controls = false;
adUiElement.style.display = 'block';
break;
case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
console.log('Ad Break Ended');
isAdBreak = false;
videoElement.controls = true;
adUiElement.style.display = 'none';
break;
default:
break;
}
}
function loadStream(url) {
if(url) {
console.log('Loading:' + url);
hls.loadSource(url);
} else {
console.log('Stream Initialization Failed');
hls.loadSource(BACKUP_STREAM);
}
hls.attachMedia(videoElement);
}
處理串流中繼資料
在這個步驟中,您會為中繼資料實作事件監聽器,以在發生某些情況時通知 SDK 就會發生這類情況廣播中繼資料事件的監聽作業可能因情況而異 串流格式 (HLS 或 DASH)、串流類型 (直播或隨選影片)、 以及所用的 DAI 後端類型。請參閱計時賽 中繼資料 指南。
HLS 串流格式 (直播和 VOD 串流、HLS.js 播放器)
如果您使用的是 HLS.js 播放器,請監聽 HLS.js FRAG_PARSING_METADATA
事件,取得 ID3 中繼資料,並透過 StreamManager.processMetadata()
將其傳遞至 SDK。
如要在所有內容載入並準備就緒後自動播放影片,請聆聽
觸發播放的 HLS.js MANIFEST_PARSED
事件。
function loadStream(streamID) {
hls.loadSource(url);
hls.attachMedia(videoElement);
// Timed metadata is passed HLS stream events to the streamManager.
hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
}
function parseID3Events(event, data) {
if (streamManager && data) {
// For each ID3 tag in the metadata, pass in the type - ID3, the
// tag data (a byte array), and the presentation timestamp (PTS).
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
}
function startPlayback() {
console.log('Video Play');
videoElement.play();
}
DASH.js (DASH 串流格式、直播和 VOD 串流類型)
如果您使用的是 DASH.js 播放器,則必須使用不同的字串來收聽直播或 VOD 串流的 ID3 中繼資料:
- 直播:
'https://developer.apple.com/streaming/emsg-id3'
- VOD 串流:
'urn:google:dai:2018'
使用 StreamManager.processMetadata()
將 ID3 中繼資料傳遞至 SDK。
如要在載入內容並準備就緒後自動顯示影片控制項,請按照下列步驟操作:
監聽 DASH.js MANIFEST_LOADED
事件。
const googleLiveSchema = 'https://developer.apple.com/streaming/emsg-id3';
const googleVodSchema = 'urn:google:dai:2018';
dashPlayer.on(googleLiveSchema, processMetadata);
dashPlayer.on(googleVodSchema, processMetadata);
dashPlayer.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
function processMetadata(metadataEvent) {
const messageData = metadataEvent.event.messageData;
const timestamp = metadataEvent.event.calculatedPresentationTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with dash.js.
streamManager.processMetadata('ID3', messageData, timestamp);
}
function loadlistener() {
showControls();
// This listener must be removed, otherwise it triggers as addional
// manifests are loaded. The manifest is loaded once for the content,
// but additional manifests are loaded for upcoming ad breaks.
dashPlayer.off(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
}
含有直播的 Shaka 播放器 (DASH 串流格式)
如果您使用 Shaka player 進行串流播放,請使用字串 'emsg'
監聽中繼資料事件。然後在對 StreamManager.onTimedMetadata()
的呼叫中使用事件訊息資料。
shakaPlayer.addEventListener('emsg', (event) => onEmsgEvent(event));
function onEmsgEvent(metadataEvent) {
// Use StreamManager.onTimedMetadata() if your video player provides
// processed metadata, as with Shaka player livestreams.
streamManager.onTimedMetadata({'TXXX': metadataEvent.detail.messageData});
}
搭配 VOD 串流的 Shaka Player (DASH 串流格式)
如果您使用 Shaka player 播放 VOD 串流,請使用字串 'timelineregionenter'
監聽結構描述事件。接著,在呼叫 StreamManager.processMetadata()
時,使用事件訊息資料搭配字串 'urn:google:dai:2018'
。
shakaPlayer.addEventListener('timelineregionenter', (event) => onTimelineEvent(event));
function onTimelineEvent(metadataEvent) {
const detail = metadataEvent.detail;
if ( detail.eventElement.attributes &&
detail.eventElement.attributes['messageData'] &&
detail.eventElement.attributes['messageData'].value ) {
const mediaId = detail.eventElement.attributes['messageData'].value;
const pts = detail.startTime;
// Use StreamManager.processMetadata() if your video player provides raw
// ID3 tags, as with Shaka player VOD streams.
streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
}
}
處理播放器事件
將事件監聽器新增至影片元素的 pause
和 start
事件,讓使用者在 SDK 暫停廣告插播時繼續播放。
function loadStream(streamUrl) {
...
videoElement.addEventListener('pause', onStreamPause);
videoElement.addEventListener('play', onStreamPlay);
}
function onStreamPause() {
console.log('paused');
if (isAdBreak) {
videoElement.controls = true;
adUiElement.style.display = 'none';
}
}
function onStreamPlay() {
console.log('played');
if (isAdBreak) {
videoElement.controls = false;
adUiElement.style.display = 'block';
}
}
大功告成!您目前透過 適用於 HTML5 的 IMA DAI SDK如要進一步瞭解其他進階 SDK 功能,請參閱 其他指南或 GitHub。