IMA SDK 可讓您輕鬆將多媒體廣告整合至網站和應用程式。IMA SDK 可從任何 符合 VAST 規定的廣告伺服器要求廣告,並管理您應用程式中的廣告播放。使用 IMA DAI SDK,應用程式會向廣告和內容影片 (VOD 或直播內容) 發出串流要求。SDK 然後會傳回合併影片串流,這樣您就不必管理應用程式內廣告和內容影片之間的切換程序。
本指南示範如何將 IMA SDK 整合到簡單的影片播放器應用程式中。如要查看或按照完整的整合範例進行操作,請從 GitHub 下載基本範例。
IMA DAI 總覽
導入 IMA DAI 時,本指南將說明兩個主要 SDK 元件:
StreamRequest
: 定義串流要求的物件。串流要求可以是隨選影片或直播。要求會指定內容 ID、API 金鑰或驗證權杖和其他參數。StreamManager
: 處理動態廣告插播串流以及與 DAI 後端互動的物件。串流管理員也會處理追蹤連線偵測 (ping),並將串流和廣告事件轉送給發布商。
必要條件
開始前必須完成以下事項:
- 請詳閱我們的相容性頁面,確認支援您預期的用途。
- 下載 Roku 播放器程式碼範例。
- 將上述範例播放器程式碼部署至 Roku 裝置,確認您的開發設定是否正常運作。
播放影片
提供的範例影片播放器直接播放內容影片。將範例播放器部署至 Roku 播放器,確保開發環境設定正確無誤。
將影片播放器變成 IMA 動態廣告插播串流播放器
建立 Sdk.xml
在專案中新增名為 Sdk.xml
的 MainScene.xml
檔案,並新增下列樣板:
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?> <component name = "imasdk" extends = "Task"> <interface> </interface> <script type = "text/brightscript"> <![CDATA[ ' Your code goes here. ]]> </script> </component>
您需要在本指南中編輯這兩個檔案。每個程式碼片段上方都有一個標題,說明您需要在哪個檔案中新增該程式碼片段。
載入 Roku 廣告架構
IMA SDK 依附於 Roku 廣告架構。如要載入架構,請將以下內容新增至 manifest
和 Sdk.xml
:
資訊清單
bs_libs_required=roku_ads_lib,googleima3
Sdk.xml
Library "Roku_Ads.brs" Library "IMA3.brs"
載入 IMA SDK
載入 IMA 動態廣告插播串流的第一步,就是載入並初始化 IMA SDK。以下程式碼會載入 IMA SDK 指令碼。
Sdk.xml
<interface> <field id="sdkLoaded" type="Boolean" /> <field id="errors" type="stringarray" /> </interface>
sub init() m.top.functionName = "runThread" End Sub sub runThread() if not m.top.sdkLoaded loadSdk() End If End Sub sub loadSdk() If m.sdk = invalid m.sdk = New_IMASDK() End If m.top.sdkLoaded = true End Sub
現在,請在 MainScene.xml
中啟動這項工作,並移除呼叫來載入內容串流。
MainScene.xml
function init() m.video = m.top.findNode("myVideo") m.video.notificationinterval = 1 loadImaSdk() end function function loadImaSdk() as void m.sdkTask = createObject("roSGNode", "imasdk") m.sdkTask.observeField("sdkLoaded", "onSdkLoaded") m.sdkTask.observeField("errors", "onSdkLoadedError") m.sdkTask.control = "RUN" end function Sub onSdkLoaded(message as Object) print "----- onSdkLoaded --- control ";message End Sub Sub onSdkLoadedError(message as Object) print "----- errors in the sdk loading process --- ";message End Sub
建立 IMA 串流播放器
接下來,您需要使用現有的 roVideoScreen
建立 IMA 串流播放器。這個串流播放器會實作三種回呼方法:loadUrl
、adBreakStarted
和 adBreakEnded
。載入串流時也請停用技巧播放功能。如此一來,使用者就不會在廣告插播開始事件前就略過片頭廣告。
Sdk.xml
<interface> <field id="sdkLoaded" type="Boolean" /> <field id="errors" type="stringarray" /> <field id="urlData" type="assocarray" /> <field id="adPlaying" type="Boolean" /> <field id="video" type="Node" /> </interface> ... sub setupVideoPlayer() sdk = m.sdk m.player = sdk.createPlayer() m.player.top = m.top m.player.loadUrl = Function(urlData) m.top.video.enableTrickPlay = false m.top.urlData = urlData End Function m.player.adBreakStarted = Function(adBreakInfo as Object) print "---- Ad Break Started ---- " m.top.adPlaying = True m.top.video.enableTrickPlay = false End Function m.player.adBreakEnded = Function(adBreakInfo as Object) print "---- Ad Break Ended ---- " m.top.adPlaying = False m.top.video.enableTrickPlay = true End Function End Sub
建立並執行串流要求
現在您已擁有串流播放器,可以建立並執行串流請求。這個示例包含直播和 VOD 串流的資料。目前正在使用 VOD 串流。
如要使用直播 (而非 VOD),將 selectedStream
從 m.testVodStream
變更為 m.testLiveStream
。
如要支援 AdUI (例如 adChoices 圖示),您也必須在請求中傳遞對包含您內容影片的節點參照。
MainScene.xml
function init() m.video = m.top.findNode("myVideo") m.video.notificationinterval = 1 m.testLiveStream = { title: "Live Stream", assetKey: "sN_IYUG8STe1ZzhIIE_ksA", apiKey: "", type: "live" } m.testVodStream = { title: "VOD stream" contentSourceId: "2528370", videoId: "tears-of-steel", apiKey: "", type: "vod" } loadImaSdk() end function function loadImaSdk() as void m.sdkTask = createObject("roSGNode", "imasdk") m.sdkTask.observeField("sdkLoaded", "onSdkLoaded") m.sdkTask.observeField("errors", "onSdkLoadedError") selectedStream = m.testVodStream m.videoTitle = selectedStream.title m.sdkTask.streamData = selectedStream m.sdkTask.video = m.video m.sdkTask.control = "RUN" end function
Sdk.xml
<interface> <field id="sdkLoaded" type="Boolean" /> <field id="errors" type="stringarray" /> <field id="urlData" type="assocarray" /> <field id="adPlaying" type="Boolean" /> <field id="video" type="Node" /> <field id="streamData" type="assocarray" /> <field id="streamManagerReady" type="Boolean" /> </interface>
sub runThread() if not m.top.sdkLoaded loadSdk() End If if not m.top.streamManagerReady loadStream() End If End Sub Sub loadStream() sdk = m.sdk sdk.initSdk() setupVideoPlayer() request = {} streamData = m.top.streamData if streamData.type = "live" request = sdk.CreateLiveStreamRequest(streamData.assetKey, streamData.apiKey) else if streamData.type = "vod" request = sdk.CreateVodStreamRequest(streamData.contentSourceId, streamData.videoId, streamData.apiKey) else request = sdk.CreateStreamRequest() end if request.player = m.player request.videoObject = m.top.video ' Required to support UI elements for 'Why This Ad?' and skippability request.adUiNode = m.top.video requestResult = sdk.requestStream(request) If requestResult <> Invalid print "Error requesting stream ";requestResult Else m.streamManager = Invalid While m.streamManager = Invalid sleep(50) m.streamManager = sdk.getStreamManager() End While If m.streamManager = Invalid or m.streamManager["type"] <> Invalid or m.streamManager["type"] = "error" errors = CreateObject("roArray", 1, True) print "error ";m.streamManager["info"] errors.push(m.streamManager["info"]) m.top.errors = errors Else m.top.streamManagerReady = True addCallbacks() m.streamManager.start() End If End If End Sub
新增事件監聽器並開始串流
要求串流後,只需再完成幾個步驟:新增事件監聽器以追蹤廣告進度、開始串流,以及將 Roku 訊息轉送至 SDK。請務必將所有訊息轉寄至 SDK,確保廣告播放正確無誤。
MainScene.xml
function loadImaSdk() as void m.sdkTask = createObject("roSGNode", "imasdk") m.sdkTask.observeField("sdkLoaded", "onSdkLoaded") m.sdkTask.observeField("errors", "onSdkLoadedError") selectedStream = m.testVodStream m.videoTitle = selectedStream.title m.sdkTask.streamData = selectedStream m.sdkTask.observeField("urlData", "urlLoadRequested") m.sdkTask.video = m.video m.sdkTask.control = "RUN" end function Sub urlLoadRequested(message as Object) print "Url Load Requested ";message data = message.getData() playStream(data.manifest) End Sub Sub playStream(url as Object) vidContent = createObject("RoSGNode", "ContentNode") vidContent.url = url vidContent.title = m.videoTitle vidContent.streamformat = "hls" m.video.content = vidContent m.video.setFocus(true) m.video.visible = true m.video.control = "play" m.video.EnableCookies() End Sub
Sdk.xml
sub runThread() if not m.top.sdkLoaded loadSdk() End If if not m.top.streamManagerReady loadStream() End If If m.top.streamManagerReady runLoop() End If End Sub Sub runLoop() m.top.video.timedMetaDataSelectionKeys = ["*"] m.port = CreateObject("roMessagePort") ' Listen to all fields. ' IMPORTANT: Failure to listen to the position and timedmetadata fields ' could result in ad impressions not being reported. fields = m.top.video.getFields() for each field in fields m.top.video.observeField(field, m.port) end for while True msg = wait(1000, m.port) if m.top.video = invalid print "exiting" exit while end if m.streamManager.onMessage(msg) currentTime = m.top.video.position If currentTime > 3 And not m.top.adPlaying m.top.video.enableTrickPlay = true End If end while End Sub Function addCallbacks() as Void m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback) m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback) m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback) m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback) m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback) m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback) End Function Function startCallback(ad as Object) as Void print "Callback from SDK -- Start called - " End Function Function firstQuartileCallback(ad as Object) as Void print "Callback from SDK -- First quartile called - " End Function Function midpointCallback(ad as Object) as Void print "Callback from SDK -- Midpoint called - " End Function Function thirdQuartileCallback(ad as Object) as Void print "Callback from SDK -- Third quartile called - " End Function Function completeCallback(ad as Object) as Void print "Callback from SDK -- Complete called - " End Function Function errorCallback(error as Object) as Void print "Callback from SDK -- Error called - "; error m.errorState = True End Function
新增可略過廣告的支援功能 (選用)
如要支援可略過的廣告,您需要將 seek
方法加進 IMA SDK 的 player 物件,以程式輔助方式搜尋影片到指定位置 (以浮點秒數表示)。
Sdk.xml
... m.player.loadUrl = Function(urlData) m.top.video.enableTrickPlay = false m.top.urlData = urlData End Function m.player.seek = Function(timeSeconds as Float) print "---- SDK requested seek to ----" ; timeSeconds m.top.video.seekMode = "accurate" m.top.video.seek = timeSeconds End Function m.player.adBreakStarted = Function(adBreakInfo as Object) print "---- Ad Break Started ---- " m.top.adPlaying = True m.top.video.enableTrickPlay = false End Function ...