DAI 用 IMA SDK を設定する

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 に依存しています。フレームワークを読み込むには、次のコードを manifestSdk.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 ストリーム プレーヤーを作成する必要があります。このストリーム プレーヤーは、loadUrladBreakStartedadBreakEnded の 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 ストリームを使用しますが、selectedStreamm.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 &lt;&gt; 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"] &lt;&gt; 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