使用 IMA SDK,即可輕鬆將多媒體廣告整合至網站和應用程式。IMA SDK 可向任何 符合 VAST 規定的廣告伺服器請求廣告,並在應用程式中管理廣告播放。應用程式可透過 IMA DAI SDK,對廣告和內容影片 (隨選影片或直播內容) 提出串流請求。SDK 接著會傳回合併的影片串流,因此您不必在應用程式中管理廣告和內容影片之間的切換。
選取您感興趣的 DAI 解決方案
全方位服務 DAI
本指南說明如何將 IMA DAI SDK 整合至簡易影片播放器應用程式。如要查看或跟著操作完整的範例整合,請從 GitHub 下載基本範例。
IMA DAI 總覽
如本指南所示,導入 IMA DAI 需要兩個主要 SDK 元件:
StreamRequest
: 定義串流要求的物件。串流要求可以是隨選影片或直播串流。直播串流請求會指定素材資源金鑰,而 VOD 請求則會指定 CMS ID 和影片 ID。這兩種要求類型都可以選擇性地加入存取指定串流所需的 API 金鑰,以及 Google Ad Manager 聯播網代碼,供 IMA SDK 處理廣告 ID,如 Google Ad Manager 設定中所指定。StreamManager
: 這個物件會處理動態廣告插播串流,以及與 DAI 後端的互動。串流管理工具也會處理追蹤 Ping,並將串流和廣告事件轉送給發布商。
必要條件
- 請詳閱相容性頁面,確認您預期的用途是否受到支援。
- 下載 Roku 範例播放器程式碼
- 將範例播放器程式碼部署到 Roku 裝置,確認開發設定正常運作。
播放影片
提供的範例影片播放器可直接播放內容影片。將範例播放器部署至 Roku 播放器,確保開發環境設定正確無誤。
將影片播放器轉換為 IMA DAI 串流播放器
請按照下列步驟導入串流播放器。
建立 Sdk.xml
在專案中新增 MainScene.xml
旁邊的 Sdk.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 Advertising Framework
IMA DAI SDK 依附於 Roku 廣告架構。如要載入架構,請在 manifest
和 Sdk.xml
中新增下列項目:
資訊清單
bs_libs_required=roku_ads_lib,googleima3
Sdk.xml
Library "Roku_Ads.brs"
Library "IMA3.brs"
載入 IMA DAI SDK
如要載入 IMA 動態廣告插播串流,第一步是載入並初始化 IMA DAI SDK。以下會載入 IMA DAI 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 串流,但您可以將 selectedStream
從 m.testVodStream
變更為 m.testLiveStream
,改用直播。
如要支援 AdUI (例如 AdChoices 圖示),您也必須在要求中傳遞含有內容影片的節點參照。
MainScene.xml
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testLiveStream = {
title: "Livestream",
assetKey: "c-rArva4ShKVIAkNfy6HUQ",
networkCode: "21775744923",
apiKey: "",
type: "live"
}
m.testVodStream = {
title: "VOD stream"
contentSourceId: "2548831",
videoId: "tears-of-steel",
networkCode: "21775744923",
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, streamData.networkCode)
else if streamData.type = "vod"
request = sdk.CreateVodStreamRequest(streamData.contentSourceId, streamData.videoId, streamData.apiKey, streamData.networkCode)
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。
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
新增對可略過廣告的支援 (選用)
如要支援可略過廣告,您需要在 IMA DAI SDK 的 player 物件中加入 seek
方法,以程式輔助方式將影片搜尋至指定位置 (以浮點秒數表示)。
如要支援可略過廣告,請務必在要求中設定 adUiNode
。
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