您可以使用 IMA SDK 輕鬆將多媒體廣告整合至網站和應用程式。IMA SDK 可向任何 符合 VAST 規定的廣告伺服器要求廣告,並管理應用程式中的廣告播放作業。透過 IMA DAI SDK,應用程式會針對廣告和內容影片 (隨選影片或直播內容) 提出串流要求。接著,SDK 會傳回合併的影片串流,因此您不必在應用程式中管理廣告和內容影片之間的切換。
選取感興趣的動態廣告解決方案
全方位服務 DAI
本指南將說明如何將 IMA DAI SDK 整合至簡易的影片播放器應用程式。如要查看或瞭解整合完成的範例,請從 GitHub 下載基本範例。
IMA DAI 總覽
實作 IMA DAI 時,需要使用兩個主要的 SDK 元件,如本指南所示:
StreamRequest
:定義串流要求的物件。串流要求可以是隨選影片或直播串流。要求會指定內容 ID,以及 API 金鑰或驗證權杖和其他參數。StreamManager
:處理動態廣告插播串流和與 DAI 後端的互動情形的物件。串流管理員也會處理追蹤 ping,並將串流和廣告事件轉送給發布商。
必要條件
- 請詳閱相容性頁面,確認系統支援您要使用的用途。
- 下載 Roku 範例播放器程式碼
- 將播放器範例程式碼部署至 Roku 裝置,確認開發設定是否正常運作。
播放影片
提供的影片播放器範例會播放內容影片。將範例播放器部署至 Roku 播放器,確保開發環境設定正確無誤。
將影片播放器轉換為 IMA DAI 串流播放器
請按照下列步驟實作串流播放器。
建立 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 Advertising Framework
IMA DAI SDK 會依賴 Roku 廣告架構。如要載入架構,請在 manifest
和 Sdk.xml
中加入下列內容:
manifest
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 串流的資料。這個值會使用 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: "sN_IYUG8STe1ZzhIIE_ksA",
apiKey: "",
type: "live"
}
m.testVodStream = {
title: "VOD stream"
contentSourceId: "2548831",
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。
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