IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK は、 VAST 準拠のあらゆる広告サーバーから広告をリクエストし、アプリでの広告再生を管理できます。IMA DAI SDK を使用すると、アプリは広告とコンテンツ動画(VOD またはライブ コンテンツ)のストリーム リクエストを行います。SDK は結合された動画ストリームを返すため、アプリ内で広告とコンテンツの動画を切り替える必要はありません。
関心のある DAI ソリューションを選択する
フルサービス DAI
このガイドでは、IMA DAI SDK をシンプルな動画プレーヤー アプリに統合する方法について説明します。完成したサンプル統合を確認または実行する場合は、GitHub から基本的なサンプルをダウンロードしてください。
IMA DAI の概要
このガイドで説明するように、IMA DAI の実装には 2 つの主要な SDK コンポーネントが含まれます。
StreamRequest
: ストリーム リクエストを定義するオブジェクト。ストリーム リクエストは、ビデオ オンデマンドまたはライブ ストリームのいずれかになります。ライブ ストリームのリクエストではアセットキーが指定され、VOD のリクエストでは CMS ID と動画 ID が指定されます。どちらのリクエスト タイプにも、指定されたストリームへのアクセスに必要な API キーと、Google アド マネージャーの設定で指定された広告識別子を IMA SDK が処理するための Google アド マネージャー ネットワーク コードを任意で含めることができます。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 Advertising Framework に依存しています。フレームワークを読み込むには、次のコードを 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
の 3 つのコールバック メソッドを実装します。また、ストリームが読み込まれたらトリック プレイを無効にします。これにより、広告ブレーク開始イベントがトリガーされる前に、ユーザーがプレロール広告の開始直後にスキップすることを防ぐことができます。
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
に変更することで、ライブ ストリームを使用できます。
adChoices アイコンなどの AdUI をサポートするには、リクエストの一部として、コンテンツ動画を含むノードへの参照も渡す必要があります。
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