IMA SDK memudahkan pengintegrasian iklan multimedia ke dalam situs dan aplikasi Anda. IMA SDK dapat meminta iklan dari server iklan apa pun yang sesuai dengan VAST dan mengelola pemutaran iklan di aplikasi Anda. Dengan IMA DAI SDK, aplikasi membuat permintaan streaming untuk video iklan dan konten—baik VOD maupun konten live. SDK kemudian menampilkan streaming video gabungan, sehingga Anda tidak perlu mengelola peralihan antara iklan dan video konten dalam aplikasi.
Pilih solusi DAI yang Anda minati
Panduan ini menunjukkan cara memutar Penayangan Pod DAI secara live atau streaming VOD, menggunakan IMA DAI SDK untuk Roku.
Ringkasan Penayangan Pod IMA DAI
Mengimplementasikan penayangan pod menggunakan IMA DAI melibatkan dua komponen SDK utama, yang ditunjukkan dalam panduan ini:
StreamRequest.createPodLiveStreamRequest()
/StreamRequest.createPodVodStreamRequest()
: Membuat objek yang menentukan permintaan streaming ke server iklan Google. Permintaan ini menentukan Kode Jaringan, danima.StreamRequest
Live Pod juga memerlukan Kunci Aset Kustom, serta kunci API opsional.StreamManager
: Objek yang menangani komunikasi antara streaming video dan IMA DAI SDK, seperti mengaktifkan ping pelacakan dan meneruskan peristiwa streaming ke penayang.
Selain itu, Anda perlu membuat permintaan ke server manipulasi manifes untuk mengambil manifes aliran untuk ditampilkan oleh aplikasi Anda. Proses yang tepat dapat memvariasikan partner teknologi video (VTP) hingga VTP.
Prasyarat
- Baca halaman kompatibilitas kami untuk memastikan kasus penggunaan yang Anda inginkan didukung.
- Download kode pemutar contoh Roku.
- Deploy contoh kode pemutar ke perangkat Roku untuk memverifikasi bahwa penyiapan pengembangan Anda berfungsi.
Putar video Anda
Contoh pemutar video yang disediakan akan memutar video konten secara otomatis. Deploy pemutar contoh ke perangkat Roku untuk memastikan lingkungan pengembangan Anda sudah disiapkan dengan benar.
Mengubah pemutar video menjadi pemutar streaming IMA DAI
Ikuti langkah-langkah berikut untuk menerapkan pemutar streaming.
Membuat Sdk.xml
Tambahkan file baru ke project Anda bersama MainScene.xml
yang disebut Sdk.xml
, dan
tambahkan boilerplate berikut:
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>
Anda perlu mengedit kedua file ini (MainScene.xml
dan Sdk.xml
) di seluruh
panduan ini.
Memuat Framework IMA DAI SDK
Untuk memuat framework, tambahkan kode berikut ke manifest
dan Sdk.xml
:
manifes
bs_libs_required=googleima3
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
]]>
</script>
</component>
Menginisialisasi IMA DAI SDK
Langkah pertama untuk memuat aliran Penyisipan Iklan Dinamis IMA Anda adalah memuat dan melakukan inisialisasi IMA DAI SDK. Perintah berikut melakukan inisialisasi skrip IMA DAI SDK.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
sub init()
m.top.functionName = "runThread"
end sub
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
end sub
sub initializeIMASDK()
if m.sdk = invalid
m.sdk = New_IMASDK()
end if
m.top.IMASDKInitialized = true
end sub
]]>
</script>
</component>
Sekarang, mulai tugas ini di MainScene.xml
dan hapus panggilan untuk memuat aliran
konten.
MainScene.xml
<?xml version="1.0" encoding="utf-8" ?>
<component extends="Scene" initialFocus="myVideo" name="MainScene">
<script type="text/brightscript">
<![CDATA[
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
sub handleIMASDKInitialized()
' Follow your manifest manipulator (VTP) documentation to register a user
' streaming session if needed.
end sub
sub handleIMASDKErrors(message as object)
print "------ IMA DAI SDK failed ------"
if message <> invalid and message.getData() <> invalid
print "IMA DAI SDK Error ";message.getData()
end if
end sub
]]>
</script>
<children>
<Video height="720" id="myVideo" visible="false" width="1280"/>
</children>
</component>
Membuat pemutar streaming IMA
Selanjutnya, Anda harus menggunakan roVideoScreen
yang ada untuk membuat pemutar streaming
IMA.
Penayangan pod live stream
Untuk live stream, pemutar streaming ini menerapkan tiga metode callback:
streamInitialized
, adBreakStarted
, dan adBreakEnded
.
Nonaktifkan juga trik play saat streaming dimuat. Tindakan ini mencegah pengguna melewati pre-roll begitu video dimulai, sebelum peristiwa jeda iklan dimulai.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
m.top.videoNode.enableTrickPlay = false
m.top.urlData = urlData
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
Penayangan pod streaming VOD
Untuk streaming VOD, pemutar streaming ini menerapkan empat metode callback: streamInitialized
, loadUrl
, adBreakStarted
, dan adBreakEnded
. Dalam
callback streamInitialized
, pastikan untuk memanggil
StreamManager.loadThirdPartyStream()
. Jika hal ini tidak dilakukan, SDK tidak akan memicu fungsi loadUrl
.
Pada langkah ini, Anda juga meminta URL streaming dari partner teknologi video
(VTP) dengan ID streaming yang diperoleh di loadAdPodStream()
. Kemudian, panggil
StreamManager.loadThirdPartyStream()
dengan manifes pod iklan dan
subjudul yang ditampilkan oleh VTP Anda.
Nonaktifkan juga trik play saat streaming dimuat. Tindakan ini mencegah pengguna melewati pre-roll begitu video dimulai, sebelum peristiwa jeda iklan dimulai.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="adStitchedStreamInfo" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub loadThirdPartyStream(adStitchedManifest as string, subtitleConfig as dynamic)
m.streamManager.loadThirdPartyStream(adStitchedManifest, subtitleConfig)
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
adStitchedManifest = m.top.streamParameters.VTPManifest.replace("[[STREAMID]]", urlData.streamId)
loadThirdPartyStream(adStitchedManifest, m.top.streamParameters.subtitleConfig)
end function
m.player.loadUrl = function(streamInfo)
m.top.adStitchedStreamInfo = streamInfo
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
Membuat dan menjalankan permintaan streaming penayangan pod VOD atau live
Setelah memiliki pemutar streaming, Anda dapat membuat dan menjalankan permintaan streaming.
Contoh ini memiliki data untuk streaming penayangan pod yang disimpan di
m.testPodServingStream
.
Penayangan pod live stream
Pada objek m.testPodServingStream
, simpan parameter yang diperlukan Google Ad
Manager untuk mengidentifikasi aliran data yang dimaksud, seperti kode jaringan dan
kunci aset kustom. Simpan juga URL manifes yang digunakan untuk mengakses server manipulasi
manifes Anda. Dalam hal ini, URL manifes harus menambahkan ID Aliran Data Google setelah permintaan streaming ditampilkan.
Agar dapat mendukung AdUI, seperti ikon adChoices, Anda juga harus meneruskan referensi ke node yang berisi video konten sebagai bagian dari permintaan Anda.
MainScene.xml
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Test live stream for DAI Pod Serving",
assetKey: "test-live-stream",
networkCode: "your-network-code",
manifest: "https://.../master.m3u8?stream_id=[[STREAMID]]",
apiKey: ""
}
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
Sdk.xml
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodLiveStreamRequest(m.top.streamParameters.assetKey, m.top.streamParameters.networkCode, m.top.streamParameters.apiKey)
' Set the player object so that the request can trigger the player's
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
Penayangan pod streaming VOD
Pada objek m.testPodServingStream
, Anda akan menyimpan kode jaringan yang digunakan dalam permintaan streaming, sehingga Google Ad Manager dapat memberikan ID aliran data. Selain itu, simpan
URL manifes yang digunakan untuk mengakses manifes tertentu pengguna di server
manipulasi manifes Anda.
Agar dapat mendukung AdUI, seperti ikon adChoices, Anda juga harus meneruskan referensi ke node yang berisi video konten Anda sebagai bagian dari permintaan Anda.
MainScene.xml
sub init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Pod Serving VOD Stream",
networkCode: "your-network-code",
VTPManifest: "https://.../manifest.m3u8?gam-stream-id=[[STREAMID]]",
subtitleConfig: []
}
runIMASDKTask()
end sub
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodVodStreamRequest(m.top.streamParameters.networkCode)
' Set the player object so that the request can trigger the player
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
Menambahkan pemroses peristiwa dan memulai streaming
Penayangan pod live stream
Setelah meminta streaming, hanya ada beberapa hal yang perlu dilakukan: menambahkan pemroses peristiwa untuk melacak progres iklan dan meneruskan pesan Roku ke SDK. Anda harus meneruskan semua pesan ke SDK untuk memastikan pemutaran iklan yang benar. Jika tidak dilakukan, tampilan iklan tidak akan dilaporkan dengan benar.
Pada langkah ini, Anda juga akan menambahkan fungsi untuk mengganti makro [[STREAMID]]
dengan ID streaming dan meneruskan URL permintaan manifes yang sudah selesai ke pemutar video.
Penerapan ini mendapatkan ID streaming pada langkah ini, tetapi bergantung pada integrasi VTP Anda, ID tersebut mungkin tersedia sebelum langkah ini.
MainScene.xml
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end function
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
manifest = m.testPodservingStream.manifest.Replace("[[STREAMID]]", adPodStreamInfo.streamId)
playStream(manifest, adPodStreamInfo.format)
end sub
sub playStream(url as string, format as string)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.url = url
vidContent.title = m.testPodservingStream.title
vidContent.streamformat = format
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.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
print "exiting"
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 And not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
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 sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
function errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end function
Penayangan pod streaming VOD
Setelah meminta streaming, hanya ada beberapa hal yang perlu dilakukan: menambahkan pemroses peristiwa untuk melacak progres iklan dan meneruskan pesan Roku ke SDK. Anda harus meneruskan semua pesan ke SDK untuk memastikan pemutaran iklan yang benar. Kegagalan untuk melakukannya akan menyebabkan tampilan iklan dilaporkan dengan tidak benar.
MainScene.xml
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end sub
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
end sub
sub playStream(url as string, format as string, subtitleConfig as object)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.title = m.testPodservingStream.title
vidContent.url = url
vidContent.subtitleConfig = subtitleConfig
vidContent.streamformat = format
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.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 and not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
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 sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
sub errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end sub