IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK では、 VAST 準拠の広告サーバーから広告をリクエストし、アプリ内での広告再生を管理できます。IMA DAI SDK を使用すると、アプリは広告とコンテンツ動画(VOD またはライブ コンテンツ)のストリーム リクエストを行います。SDK は結合された動画ストリームを返すため、アプリ内で広告とコンテンツ動画の切り替えを管理する必要がありません。
このガイドでは、簡単な動画プレーヤー アプリに IMA SDK を統合する方法について説明します。統合のサンプルを確認する場合は、GitHub から基本的なサンプルをダウンロードしてください。
IMA DAI の概要
IMA DAI の実装には、このガイドで説明する次の 2 つの主要な SDK コンポーネントが含まれます。
StreamRequest
: ストリーム リクエストを定義するオブジェクト。ストリーム リクエストは、ビデオ オンデマンドまたはライブ ストリームのいずれかになります。リクエストには、コンテンツ ID のほか、API キーまたは認証トークンなどのパラメータを指定します。StreamManager
: ダイナミック広告挿入ストリームと DAI バックエンドとのやり取りを処理するオブジェクト。また、ストリーム マネージャーはトラッキング ping を処理し、ストリームと広告のイベントをパブリッシャーに転送します。
前提条件
始める前に、次のことを行う必要があります。
- 互換性ページを読み、目的のユースケースがサポートされているかどうか確認してください。
- Roku のサンプル プレーヤー コードをダウンロードします。
- 上記のサンプル プレーヤー コードを Roku デバイスにデプロイして、開発用設定が機能していることを確認します。
動画の再生
用意されているサンプル動画プレーヤーでは、コンテンツ動画が自動的に再生されます。サンプル プレーヤーを Roku プレーヤーにデプロイし、開発環境が適切にセットアップされていることを確認します。
動画プレーヤーを IMA ダイナミック広告挿入ストリーム プレーヤーに変換
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 広告フレームワークを読み込む
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 ストリーム プレーヤーを作成する必要があります。
このストリーム プレーヤーは、3 つのコールバック メソッド(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
に変更します。
adChoices アイコンなどの AdUI をサポートするには、リクエストの一部としてコンテンツ動画を含むノードへの参照も渡す必要があります。
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
スキップ可能な広告のサポートを追加する(省略可)
スキップ可能な広告をサポートするには、IMA SDK のプレーヤー オブジェクトに seek
メソッドを追加し、指定した位置(浮動小数点秒単位)で動画をプログラムによってシークする必要があります。
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 ...