互動式媒體廣告 (IMA) 動態廣告插入 (DAI) SDK 會使用串流媒體區段 (頻帶內中繼資料) 或串流資訊清單檔案 (資訊清單內中繼資料) 中嵌入的中繼資料資訊,追蹤觀眾的位置和用戶端廣告事件。中繼資料會以不同格式傳送,具體取決於播放的串流類型。
影片播放器會分批接收時間指定中繼資料。視播放器而定,中繼資料可在預定時間或以批次方式顯示。每個中繼資料字串都會附帶相關聯的呈現時間戳記 (PTS),指出應觸發的時間。
您的應用程式負責擷取中繼資料,並將其轉送至 IMA DAI SDK。SDK 提供以下方法傳遞這項資訊:
- onTimedMetadata
這個方法會將可供處理的中繼資料字串轉送至 SDK。這個函式只需要一個引數:
metadata
:物件包含TXXX
鍵,且相關聯的字串值前面有google_
。
- processMetadata
這個方法會排定中繼資料字串,以便在指定的 PTS 之後由 SDK 處理。這個方法會使用下列引數:
type
:包含所處理事件類型的字串。可接受的值為 HLS 的ID3
或 DASH 的urn:google:dai:2018
data
:字串值的前置字元為google_
,或是符合以下格式的位元組陣列:ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx
。timestamp
:應處理資料的時間戳記 (以秒為單位)。
IMA DAI SDK 支援的每種串流類型都會使用獨特形式的時限設定,如以下各節所述。
HLS MPEG2TS 串流
使用 MPEG2TS 區段的線性 DAI HLS 串流會透過頻帶內 ID3 標記,將時間指定中繼資料傳遞至影片播放器。這些 ID3 標記會嵌入 MPEG2TS 區段,並指定為 TXXX 欄位名稱 (用於自訂使用者定義的文字內容)。
在 Safari 中播放
Safari 會自動處理 ID3 標記,做為隱藏的音軌,因此 cuechange 事件會在正確的時間觸發,以便處理每個中繼資料。無論內容或類型為何,您都可以將所有中繼資料傳遞至 IMA DAI SDK。系統會自動篩除不相關的結構描述。
範例如下:
videoElement.textTracks.addEventListener('addtrack', (e) => {
const track = e.track;
if (track.kind === 'metadata') {
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
for (const cue of track.activeCues) {
const metadata = {};
metadata[cue.value.key] = cue.value.data;
streamManager.onTimedMetadata(metadata);
}
});
}
});
...
HLS.js
HLS.js 會透過 FRAG_PARSING_METADATA
事件以批次方式提供 ID3 標記,做為樣本陣列。HLS.js 不會將 ID3 資料從位元組陣列轉譯為字串,也不會將事件偏移至對應的 PTS。您不需要將樣本資料從位元組陣列解碼為字串,或篩除不相關的 ID3 標記,因為 IMA DAI SDK 會自動執行這項解碼和篩選作業。
範例如下:
hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
if (streamManager && data) {
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
});
...
HLS CMAF 串流
使用通用媒體應用程式架構 (CMAF) 的線性 DAI HLS 串流會依循 ID3 透過 CMAF 標準,透過頻道內 eMSGv1 方塊傳遞時間中繼資料。這些 eMSG 方塊會嵌入每個媒體片段的開頭,每個 ID3 eMSG 都包含與串流中最後一個中斷點相關的 PTS。
自 HLS.js 1.2.0 版起,我們建議的播放器會透過 CMAF 將 ID3 傳遞給使用者,就像是 ID3 標記一樣。因此,以下範例與 HLS MPEG2TS 串流相同。不過,並非所有播放器都支援這項功能,因此實作 HLS CMAF 串流支援功能時,可能需要透過 eMSG 解析 ID3 的專屬程式碼。
在 Safari 中播放
Safari 會將透過 eMSG 中繼資料提供的 ID3 視為偽 ID3 事件,並自動以批次形式提供這些資料做為隱藏音軌,以便在正確時間觸發 cuechange 事件,處理每個中繼資料。無論是否與時間相關,您都可以將所有中繼資料傳遞至 IMA DAI SDK。系統會自動篩除所有非 DAI 相關的中繼資料。
範例如下:
videoElement.textTracks.addEventListener('addtrack', (e) => {
const track = e.track;
if (track.kind === 'metadata') {
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
for (const cue of track.activeCues) {
const metadata = {};
metadata[cue.value.key] = cue.value.data;
streamManager.onTimedMetadata(metadata);
}
});
}
});
...
HLS.js
自 1.2.0 版起,HLS.js 會將透過 eMSG 中繼資料提供的 ID3 視為偽 ID3 事件,並透過 FRAG_PARSING_METADATA
事件以樣本陣列的形式批次提供。HLS.js 不會將 ID3 資料從位元組陣列轉譯為字串,也不會將事件偏移至對應的 PTS。您不必將樣本資料從位元組陣列解碼為字串,因為 IMA DAI SDK 會自動執行這項解碼作業。
範例如下:
hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
if (streamManager && data) {
data.samples.forEach((sample) => {
streamManager.processMetadata('ID3', sample.data, sample.pts);
});
}
});
...
DASH 串流
線性 DAI DASH 串流會在事件串流中以自訂 schemeIdUri
值 urn:google:dai:2018
的資訊清單事件傳遞中繼資料。這些串流中的每個事件都包含文字酬載和 PTS。
DASH.js
Dash.js 會根據每個事件串流的 schemeIdUri 值提供自訂事件處理常式。這些自訂處理常式會以批次方式觸發,您可以自行處理 PTS 值,以便正確設定事件時間。IMA DAI SDK 可透過 streamManager 方法 processMetadata()
為您處理這項作業。
範例如下:
const dash = dashjs.MediaPlayer().create();
dash.on('urn:google:dai:2018', (payload) => {
const mediaId = payload.event.messageData;
const pts = payload.event.calculatedPresentationTime;
streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
});
...
Shaka Player
Shaka Player 會將事件顯示為 timelineregionenter
事件的一部分。由於格式與 Shaka Player 不相容,因此必須透過詳細屬性 eventNode.attributes['messageData']
擷取原始中繼資料值。
範例如下:
player.addEventListener('timelineregionenter', function(event) {
const detail = event.detail;
if ( detail.eventNode.attributes &&
detail.eventNode.attributes['messageData']) {
const mediaId = detail.eventNode.attributes['messageData'];
const pts = detail.startTime;
streamManager.processMetadata("urn:google:dai:2018", mediaId, pts);
}
});
...
廣告連播放送
針對 Pod 放送,您可以根據下列條件,設定不同的設定來傳遞定時中繼資料:
- 直播或 VOD 串流類型
- 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 Player (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);
}
}