廣告插播時間點

總覽

Web Receiver SDK 具有特定媒體串流內廣告插播和隨播廣告的原生支援,提供 API,可用於設定廣告插播的時間點、廣告來源、廣告插播時間點,以及相關聯的中斷片段。在本指南中,Break 是指內含一或多個廣告或串場廣告的播放作業,而每則廣告或串場廣告稱為 BreakClip。這些中斷問題與正在載入或播放的媒體相關聯。

廣告類型

Web Receiver SDK 支援用戶端廣告插播 (CSAI) 和伺服器拼接廣告 (SSAI) 功能。用戶端拼接廣告是由應用程式手動設定,或從 VASTVMAP 範本檔案擷取。伺服器拼接廣告必須在內容載入之前指定為嵌入廣告,或是在內容播放期間以內嵌展開廣告動態方式手動指定。以下將詳細說明每種廣告類型的實作方式。

手動拼接用戶端

手動用戶端拼接廣告插播是一種廣告插播,由用戶端共同拼接,並且使用 SDK API 由應用程式手動指定。這個廣告類型未嵌入在主要內容的串流中。BreakClip 必須提供 contentId,這是指向廣告素材的網址、contentType 描述廣告素材格式,以及 title

Break 必須將 isEmbeddedexpanded 設為預設值 falseposition 可設定為片頭廣告片中廣告片尾廣告廣告插播 (詳情請參閱廣告插播定位部分)。準備播放廣告時,Web Receiver SDK 會產生另一個播放器執行個體來載入並播放廣告內容。這些中斷點需要 stitched timeline,因此您必須靜態加入 (詳情請參閱廣告插播一節)。以下範例說明手動用戶端拼接廣告的基本導入:

// Create the BreakClip.
let clipClient = new cast.framework.messages.BreakClip('bc_client');
clipClient.title = 'The Ad Title to be displayed during playback';
clipClient.contentId = 'https://example.com/ad.m3u8';
clipClient.contentType = 'application/vnd.apple.mpegurl';

// Optional: Used when HLS ad container formats differ from the main content's.
clipClient.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;

// Create the Break using the BreakClip id above.
let breakPostrollClient = new cast.framework.messages.Break(
    'break_postroll_client', ['bc_client'], -1);
breakPostrollClient.isEmbedded = false; // Optional: default is false.
breakPostrollClient.expanded = false; // Optional: default is false.

VAST

Web Receiver SDK 支援新增 IAB 標準 VAST (影片廣告放送範本) 廣告。提供時,系統會剖析 XML 範本,以便在進入廣告插播時產生後續的「client-stitched」片段片段。

如要建立 VAST 廣告,接收器必須建立 VastAdsRequest,並在 BreakClip vastAdsRequest 屬性中指定。VastAdsRequest 物件必須定義 adsResponse (XML 範本本身的字串表示法) 或 adTagUrl (代管 XML 範本的網址) 屬性。如果指定網址,SDK 會處理範本擷取作業。封裝 Break 時會遵循用戶端拼接廣告的慣例。這類廣告可以與一個相同用戶端的手動拼接廣告一起插播,或是在同一內容的不同獨立廣告片段中單獨插入。以下範例顯示 VAST 廣告的基本導入:

// Create the VastAdsRequest.
let vastTemplate = new cast.framework.messages.VastAdsRequest();
vastTemplate.adTagUrl = 'https://example.com/ads.xml'

// Create the BreakClip.
let clipVast = new cast.framework.messages.BreakClip('bc_vast');
clipVast.vastAdsRequest = vastTemplate;

// Create the Break using the BreakClip id above.
let breakPostrollVast = new cast.framework.messages.Break(
    'break_postroll_vast', ['bc_vast'], -1);
breakPostrollVast.isEmbedded = false; // Optional: default is false.
breakPostrollVast.expanded = false; // Optional: default is false.

輸入包含 VAST BreakClipBreak 時,Web Receiver SDK 會視需要擷取內容,然後剖析範本。在剖析時,SDK 會產生新的 BreakClip,並填入從範本、contentIdtitledurationwhenSkippableclickThroughUrl 等範本中擷取到的值。contentType產生的中斷片段的 id 會設為 GENERATED:N,其中 N 是整數,以 1 為開頭建立的每個 VAST 廣告插播片段遞增 10然後將產生的廣告新增至 BreakClip 陣列中。系統會將每個 Break 中每個 VAST 廣告插播片段的 id,替換成對應的產生的中斷片段 id 。下列程式碼片段說明在這種廣告插播時間點之後與廣告相關的 MEDIA_STATUS 訊息變更。

BreakBreakClip 資訊,然後再使用 VAST 廣告插播廣告。

"breaks": [
  {
    "id": "break_postroll_vast",
    "breakClipIds": [
      "bc_vast"
    ],
    "position": 0,
    "isWatched": false
  }
],
"breakClips": [
  {
    "id": "bc_vast"
  }
]

BreakBreakClip 資訊輸入 VAST 廣告後的顯示資訊。

"breaks": [
  {
    "id": "break_postroll_vast",
    "breakClipIds": [
      "GENERATED:0"
    ],
    "position": 0,
    "isWatched": true
  }
],
"breakClips": [
  {
    "id": "bc_vast"
  },
  {
    "id": "GENERATED:0",
    "contentId": "https://example.com/break-clip-1.mpd",
    "contentType": "application/dash+xml",
    "title": "Ad Title Extracted from Template",
    "duration": 10,
    "whenSkippable": 5,
    "clickThroughUrl": "https://example.com/ad-target"
  }
]

VMAP

Web Receiver SDK 支援 IAB VMAP (影片多重廣告播放清單) 標準。提供 VMAP 後,Web Receiver SDK 會剖析 VMAP 回應,並為回應中的任何 <AdBreak> 項目產生用戶端拼接 Break 物件。這也會產生適當的 BreakClips,並為 VMAP 中提供的每個 <AdSource> 項目產生 vastAdsRequest 物件。為了讓 VMAP 插入內容,應用程式必須建立 VastAdsRequest 物件,並指派給 LoadRequestDataMediaInformationvmapAdsRequest 屬性。這類廣告必須以靜態的方式插入 (詳情請參閱廣告插入一節)。以下程式碼片段概述建立 VMAP 要求的建立方式。

// Create the VastAdsRequest.
let vastTemplate = new cast.framework.messages.VastAdsRequest();
vastTemplate.adTagUrl = 'https://example.com/vmap.xml'

// Add it to the MediaInformation of the LoadRequest.
loadRequestData.media.vmapAdsRequest = vastTemplate;

已嵌入

內嵌廣告插播是一種廣告插播時間點,會將主要廣告拼接到主要內容串流中。計算媒體時間時,Break 的時間與主要內容的時間長度無關

BreakClip 必須提供廣告素材的 durationtitleBreak 必須將 isEmbedded 設為 true,並將 expanded 設為 falseposition 可設為片頭廣告片中廣告廣告插播時間點。片尾廣告插播支援正專屬的 position 值。詳情請參閱中斷位置一節。廣告觸發播放時,Web Receiver SDK 會內嵌廣告片段,繼續播放串流。這個廣告類型沒有額外的載入機制。播放頭在中斷時間範圍後,系統就會向使用者顯示相關的廣告中繼資料。這些中斷點需要 embedded timeline 且必須靜態加入 (詳情請參閱廣告插播一節)。以下範例顯示 embedded 廣告的基本導入。

// Create the BreakClip.
let clipEmbedded = new cast.framework.messages.BreakClip('bc_embedded');
clipEmbedded.title = 'The Ad Title to be displayed during playback';
clipEmbedded.duration = 15;

// Create the Break using the BreakClip id above.
let breakPrerollEmbedded = new cast.framework.messages.Break(
    'break_preroll_embedded', ['bc_embedded'], 0);
breakPrerollEmbedded.isEmbedded = true;
breakPrerollEmbedded.expanded = false; // Optional: default is false.

已展開內嵌檔案

內嵌展開廣告插播是一種廣告插播時間點,會將主要廣告拼接在主要內容串流中。計算媒體時間時,Break 會在主要內容的時間長度中納入時間長度。

BreakClip 必須提供廣告素材的 durationtitleBreak 會將 isEmbedded 設為 true,並將 expanded 設為 trueposition 可設為片頭廣告片中廣告廣告插播時間點。片尾廣告插播支援正值 position 值。詳情請參閱中斷位置一節。廣告觸發播放時,Web Receiver SDK 會內嵌廣告片段,繼續播放串流。這個廣告類型沒有額外的載入機制。播放頭在中斷時間範圍後,系統就會向使用者顯示相關的廣告中繼資料。這些中斷點需要 embedded timeline,可以靜態動態新增 (詳情請參閱廣告插播一節)。以下範例說明 embedded expanded 廣告的基本導入:

// Create the BreakClip.
let clipEmbeddedExpanded =
    new cast.framework.messages.BreakClip('bc_embedded_expanded');
clipEmbeddedExpanded.title = 'The Ad Title to be displayed during playback';
clipEmbeddedExpanded.duration = 15;

// Create the Break using the BreakClip id above.
let breakPrerollEmbeddedExpanded = new cast.framework.messages.Break(
    'break_preroll_embedded_expanded', ['bc_embedded_expanded'], 0);
breakPrerollEmbeddedExpanded.isEmbedded = true;
breakPrerollEmbeddedExpanded.expanded = true;

玩家時間軸類型

建立播放器執行個體時,Web Receiver SDK 會選取時間軸類型,以便在內容播放期間支援播放廣告。每個時間軸都能新增特定的廣告插播類型。時間軸類型取決於 LoadRequestDataMediaInformation 載入期間顯示的廣告類型。如有內嵌廣告插播時間點,系統會選取 embedded 時間軸。如果用戶端已拼接廣告插播,請選取 stitched 的時間軸。 如果沒有任何廣告,SDK 預設會使用 embedded 時間軸。選取時間軸後,就無法針對目前的媒體項目進行變更。下表提供每個時間軸的詳細說明。

時間軸類型 說明
內嵌時間軸 表示支援內嵌在主要內容的廣告時間 (內嵌內嵌展開廣告插播) 的媒體時間。如果有未展開的廣告插播,系統會從內容總時間長度中扣除廣告插播的時間長度。另一方面,當廣告展開插播時,系統會將其時間視為主要內容的一部分。
拼接時間軸 呈現媒體時間,以支援外部媒體檔案的廣告 (手動用戶端拼接VASTVMAP廣告插播時間點)。加入後,廣告時段的時間長度不屬於主要內容的時間長度。

下方圖 1 到 3 說明使用多種廣告類型及其各自的時間軸值。內容設定為包含片頭廣告的插播廣告,當中含有兩個廣告插播片段,以及含有單一廣告時段片段的片中廣告片尾廣告。喚醒時鐘時間,也就是內容開始播放後、主要內容的媒體時間,以及廣告插播目前片段的播放時間點,在這兩個圖形下方對齊。

客戶拼接廣告的時間軸
圖 1:表示部分內容的時間軸,以及其中的 3 個用戶端拼接廣告插播時間點。


伺服器拼接內嵌廣告的時間軸
圖 2:顯示部分內容及其 3 個伺服器拼接內嵌廣告插播的時間軸。


伺服器拼接內嵌展開廣告的時間軸
圖 3:顯示部分內容的時間軸,以及其中的 3 個伺服器拼接內嵌展開廣告插播時間點。

廣告插播定位

透過 Web Receiver SDK,開發人員可設定 Breakposition 屬性,指定廣告插播的時間點。這個值對應主要內容的媒體時間,可用於建立 pre-rollmid-rollpost-roll 廣告插播。定義如下:

廣告插播位置 說明
片頭廣告 在主要內容之前播放的廣告插播。這代表將 breakPosition 設為 0
片中廣告 播放片中廣告的廣告時段。這代表將 breakPosition 設為休息時間的開始時間超過主要內容的開始時間,而結束時間的結束時間少於主要內容的結束時間。
片尾廣告 在主要內容結束後播放的廣告插播。這個屬性會將拼接時間表breakPosition 設為 -1。如果是內嵌的時間軸breakPosition 應設為主要內容的時間長度,除以廣告插播時間長度。不支援直播內容。

互通性矩陣

做為快速參考點,表 1 列出廣告類型及其與廣告相關功能的相容性。

表 1:廣告互通性矩陣
功能支援 手動拼接客戶廣告 VAST VMAP 內嵌廣告 內嵌展開廣告
相容裝置: VAST 手動拼接用戶端 已展開內嵌檔案 已嵌入
時間軸 線裝 線裝 線裝 已嵌入 已嵌入
廣告插播 靜態 靜態 靜態 靜態 靜態、動態
廣告移除
片頭廣告
片中廣告
影片後插播廣告
廣告略過
廣告插播中斷攔截器
中斷片段載入攔截器

活動

當發生按鍵中斷事件時,層級轉換 SDK 會調度 BreaksEvent 類型的事件。接收器應用程式可以使用 PlayerManager addEventListener API 訂閱。

這些事件可用於數據分析和廣告播放追蹤。使用 VMAP (影片多重廣告播放清單) 和 VAST (影片廣告放送範本) 廣告時,SDK 會自動分派出回應中的所有標準追蹤事件。

事件類型列於表 2,以及觸發事件的詳細說明。

中斷事件生命週期
圖 4:廣告插播事件生命週期。
表 2:中斷事件及其說明。
分組事件 說明
BREAK_STARTED 主要內容目前的媒體時間等於未觀看片段的 position 時觸發。
BREAK_CLIP_LOADING 只有在拼接時間軸中斷載入開始時,才會觸發。
BREAK_CLIP_STARTED 廣告插播片段開始播放時觸發。
BREAK_CLIP_ENDED 廣告插播片段結束時觸發。在下列情況下,系統會填入 endedReason
  • 已完全拼接的時間軸片段。
  • 拼接的時間軸將片段片段轉換到其他中斷片段。
  • 系統會略過任何休息片段。
  • 最後一個插播片段會完整播放片尾廣告,
  • 發生錯誤。
BREAK_ENDED 在廣告插播中的最後一個休息片段結束時觸發。

插入廣告

Cast SDK 可讓應用程式在投放工作階段的不同時間點插入及移除廣告。這類廣告分為「靜態」和「動態」這兩種類型。 靜態廣告插播必須在 LoadRequestData 之前指定廣告,才能建立玩家。動態廣告插入會使用 BreakManager addBreak API,在已載入的內容中插入廣告插播。每種類型的插入方法都與特定的廣告類型相容。請在互通性矩陣中提供相容性總覽。

靜態廣告插入

靜態廣告插播是指在玩家建立前加入相關的廣告中繼資料。此資訊於 LoadRequestDataMediaInformation 中提供。例如,您可以在已連結的寄件者的原始載入要求中設定這項功能,也可以使用 Web Receiver 應用程式攔截 LOAD 要求來插入。將 LoadRequestData 傳回 Web Receiver SDK 以進行處理後,系統就會建立播放器。詳情請參閱「載入媒體」。以下範例顯示 LOAD 要求攔截器新增的手動拼接廣告。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {

  // Create the BreakClip.
  let clipClient = new cast.framework.messages.BreakClip('bc_client');
  clipClient.title = 'The Ad Title to be displayed during playback';
  clipClient.contentId = 'https://example.com/ad.mp4';
  clipClient.contentType = 'video/mp4';

  // Create the Break using the BreakClip id above.
  let breakPostrollClient = new cast.framework.messages.Break(
      'break_postroll_client', ['bc_client'], -1);

  // Set the ad information in the load request data.
  let media = loadRequestData.media;
  media.breakClips = [clipClient];
  media.breaks = [breakPostrollClient];

  return loadRequestData;
});

動態廣告插播

動態廣告插播會在內容播放期間設定廣告插播的特性。方法是取得 BreakManager 的執行個體,並呼叫 addBreak API。至少需要兩個參數,即內嵌展開 BreakBreakClip 陣列。第三個第三屬性包括設為 true 時,透過 MediaStatus 廣播強制將變更傳送至已連結的寄件者。當新增中斷和中斷片段時,對應的 ID 不得重複。玩家建立後,才能新增這類廣告。網路接收器 SDK 會在玩家建立後觸發 PLAYER_LOADING 事件。請參閱以下範例,瞭解如何在事件處理常式中回應來自串流 ID3 中繼資料的變更,並建立 BreakBreakClip 物件,以便將其插入時間軸。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

playerManager.addEventListener(cast.framework.events.EventType.ID3, (event) => {

  // Create the BreakClip.
  let clipEmbeddedExpanded = parseBreakClipFromData(event.segmentData);
  let breakEmbeddedExpanded = parseExpandedBreakFromData(event.segmentData);

  // Add the break and break clip.
  breakManager.addBreak(breakEmbeddedExpanded, [clipEmbeddedExpanded]);
});

動態廣告移除

如要移除動態換行,應用程式應在播放期間呼叫 removeBreakById。這個函式會從中斷處移除中斷點的字串 ID。指定的 breakId 必須指向內嵌展開的廣告插播。如果偵測到其他類型的廣告插播,插播時間點會保留在時間軸上。請參考以下範例,瞭解如何移除中斷點。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

breakManager.removeBreakById('break_midroll_embedded_expanded');

廣告插播行為

SDK 會定義玩家進入及離開休息的預設行為,並提供使用 BreakManager 中提供的部分 API 來進一步自訂的行為。

預設廣告插播行為

在一般播放期間或從搜尋 Break 來輸入 Break 時,SDK 會檢查 isWatched 屬性,評估使用者是否已經看過該程式。建立完成後,此屬性的中斷預設值為 false。如果屬性為 true,則不會在輸入時播放中斷點,而且主要內容會繼續播放。如果屬性為 false,則會在輸入時播放迴圈。

跳轉時,預設實作會取得 position 介於搜尋作業 seekFromseekTo 值之間所有 Break 項目。在這個中斷清單中,SDK 會播放 Break,其 position 最接近 seekTo 值,且 isWatched 屬性已設為 false。然後,該休息活動的 isWatched 屬性會設為 true,播放器會開始播放中斷片段。觀看影片完畢後,主要內容會從 seekTo 位置繼續播放。如果沒有這類中斷情形,就不會播放任何中斷內容,且主要內容將會在 seekTo 位置繼續播放。

在廣告插播期間,SDK 會在 MediaStatus 中向已連結的傳送端應用程式廣播任何相關更新。這些應用程式會利用 breakStatus 屬性,透過廣播更新廣告使用者介面。這個屬性只會在廣告插播期間定義。

接收器應用程式也可以直接查詢與顯示頭部位置相關的 BreakClip 相關資訊,方法是呼叫 PlayerManager getBreakClipCurrentTimeSec。同樣地,應用程式可以呼叫 getBreakClipDurationSec 來查詢目前 BreakClip 的持續時間。

自訂廣告插播行為

您可以使用 BreakManager 提供的 setBreakClipLoadInterceptorsetBreakSeekInterceptor 方法,修改中斷和中斷片段的預設行為

廣告插播中斷攔截器

廣告插播搜尋攔截器可讓應用程式控制在廣告插播時間點搜尋的行為。當要求運算向一或多個時間點向前或向後移動時,就會觸發函式。呼叫時,BreakSeekData 會以參數的形式傳遞給回呼函式。BreakSeekData 物件包含 Break 物件的陣列,其中的 position 屬性設為目前seekFrom和搜尋目的地時間 seekTo 之間的播放頭時間。

這個攔截器可允許修改個別斷行中的 Break 物件。實作完成後,廣告插播攔截器必須傳回選用的修改 BreakSeekData 物件,以指定要播放哪一個廣告插播。玩家會繼續播放傳回值中的所有中斷點。如果 null 尋找值攔截器未傳回任何值,或是未傳回任何內容,該值就會被中斷。

請參閱下方範例,瞭解如何執行攔截器,讓其覆寫預設行為來觀察已看過廣告之外的所有插播廣告,但已觀看的廣告除外。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

breakManager.setBreakSeekInterceptor((breakSeekData) => {

  // Filter the breaks array by removing watched breaks.
  const unwatchedBreaks =
      breakSeekData.breaks.filter(adBreak => !adBreak.isWatched);
  breakSeekData.breaks = unwatchedBreaks;

  return breakSeekData;
});

中斷片段載入攔截器

使用中斷片段載入攔截器,即可在播放開始前修改 BreakClip 物件。

只有拼接時間軸中斷才會呼叫中斷片段載入攔截器,可以使用 setBreakClipLoadInterceptor 進行設定。在輸入 Break 之前,系統會針對該中斷事件中定義的個別 BreakClip 呼叫這個攔截器。SDK 會將原始 BreakClip 物件做為回呼函式的參數傳遞。然後,應用程式可以修改並傳回這個 BreakClip,讓 SDK 能夠使用更新後的設定擷取及顯示中斷子句。如果傳回 null 或未傳回任何內容,系統會略過中斷子句。

請參閱下方範例,使用公用函式呼叫 getUrlFromClipId,修改 BreakClipid 對應至網址,即可修改中斷片段的 contentUrl

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

breakManager.setBreakClipLoadInterceptor(
    (breakClip, breakClipLoadInterceptorContext) => {

  // Obtains the URL of a break clip id from a function call.
  breakClip.contentUrl = getUrlFromClipId(breakClip.id);

  return breakClip;
});

略過廣告

Web Receiver SDK 提供 API,可用於在廣告插播時間點略過廣告插播時間點和個別廣告插播片段。這個 SDK 也可讓使用者與傳送方應用程式或智慧螢幕裝置互動,選擇略過中斷片段。

使用者可略過的剪輯片段

將中斷片段設為可略過,可讓使用者與已連結的傳送端應用程式和智慧螢幕裝置互動,可選擇略過目前播放的片段。將 whenSkippable 屬性設為非負值的秒數,就能為 BreakClip 物件啟用這項功能。在廣告插播片段播放這個秒數後,播放器會把可略過的短片視為可略過。將這個值設為 0 可讓使用者立即略過廣告插播片段。

// Create the BreakClip.
let clip = new cast.framework.messages.BreakClip('bc');
clip.title = 'The Ad Title to be displayed during playback';
clip.whenSkippable = 10; // Users can skip the clip after 10 seconds of playback.

這項資訊可以在寄件者的原始載入要求或接收器應用程式中設定。略過時,拼接時間軸中的廣告插播片段會停止播放目前的中斷片段。如果存在主要內容或載入主要內容,播放器會載入下一個中斷片段。略過時,內嵌時間軸中的廣告插播片段會尋找插播片段的結尾,並在這個時間點繼續播放串流。

透過程式略過廣告

廣告也可以自動略過,無需與使用者互動。

如要略過遊戲完全中斷,應用程式應將 BreakisWatched 屬性設為 true。載入期間或內容播放期間隨時可以這麼做。主要內容目前的時間點符合 position 時,播放器會評估 isWatched 屬性。屆時,玩家會判斷是否應進入中斷狀態。請見以下範例,瞭解所有中斷點迴圈,並在玩家載入時修改該值。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

playerManager.addEventListener(cast.framework.events.EventType.PLAYER_LOADING,
    (event) => {

  // Obtain the breaks and iterate through each item to skip all ad breaks.
  let breaks = breakManager.getBreaks();
  breaks.forEach((brk) => {
    brk.isWatched = true;
  });
});

如要透過程式輔助方式略過特定中斷片段,應使用中斷片段載入攔截器。透過傳回 null 或如未在回呼函式傳回值,系統就會略過該中斷片段。

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
const breakManager = playerManager.getBreakManager();

breakManager.setBreakClipLoadInterceptor(
      (breakClip, breakClipLoadInterceptorContext) => {
  return null;
});