Начало работы с IMA DAI SDK

IMA SDK упрощают интеграцию мультимедийной рекламы на ваши веб-сайты и приложения. IMA SDK могут запрашивать рекламу с любого рекламного сервера , совместимого с VAST, и управлять воспроизведением рекламы в ваших приложениях. С помощью SDK IMA DAI приложения отправляют потоковый запрос на рекламу и видеоконтент — либо VOD, либо контент в реальном времени. Затем SDK возвращает объединенный видеопоток, так что вам не придется управлять переключением между рекламой и видеоконтентом в вашем приложении.

Выберите решение DAI, которое вас интересует

Полный сервис DAI

В этом руководстве показано, как интегрировать IMA DAI SDK в простое приложение видеоплеера. Если вы хотите просмотреть или проследить за завершенным примером интеграции, загрузите базовый пример с GitHub.

Обзор IMA DAI

Реализация IMA DAI включает в себя два основных компонента SDK, как показано в этом руководстве:

  • StreamRequest : объект, определяющий запрос потока. Запросы на поток могут относиться как к видео по запросу, так и к прямым трансляциям. В запросах указывается идентификатор контента, а также ключ API или токен аутентификации и другие параметры.
  • StreamManager : объект, который обрабатывает потоки динамической вставки рекламы и взаимодействие с серверной частью DAI. Менеджер потоков также обрабатывает отслеживание пингов и пересылает события потока и рекламы издателю.

Предварительные условия

  • Прочтите нашу страницу совместимости , чтобы убедиться, что ваш предполагаемый вариант использования поддерживается.
  • Загрузите наш пример кода проигрывателя 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

IMA DAI SDK зависит от рекламной платформы Roku. Чтобы загрузить платформу, добавьте следующее в manifest и Sdk.xml :

манифестировать

bs_libs_required=roku_ads_lib,googleima3

Sdk.xml

Library "Roku_Ads.brs"
Library "IMA3.brs"

Загрузите SDK IMA DAI

Первым шагом к загрузке потока динамической вставки объявлений 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 &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

Добавьте поддержку пропускаемых объявлений (необязательно).

Чтобы поддерживать рекламу с возможностью пропуска, необходимо добавить метод seek в объект проигрывателя IMA DAI SDK, который программно ищет видео в указанном месте за секунды с плавающей запятой.

Для поддержки пропускаемой рекламы вы также должны убедиться, что вы установили 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
,

IMA SDK упрощают интеграцию мультимедийной рекламы на ваши веб-сайты и приложения. IMA SDK могут запрашивать рекламу с любого рекламного сервера , совместимого с VAST, и управлять воспроизведением рекламы в ваших приложениях. С помощью SDK IMA DAI приложения отправляют потоковый запрос на рекламу и видеоконтент — либо VOD, либо контент в реальном времени. Затем SDK возвращает объединенный видеопоток, так что вам не придется управлять переключением между рекламой и видеоконтентом в вашем приложении.

Выберите решение DAI, которое вас интересует

Полный сервис DAI

В этом руководстве показано, как интегрировать IMA DAI SDK в простое приложение видеоплеера. Если вы хотите просмотреть или проследить за завершенным примером интеграции, загрузите базовый пример с GitHub.

Обзор IMA DAI

Реализация IMA DAI включает в себя два основных компонента SDK, как показано в этом руководстве:

  • StreamRequest : объект, определяющий запрос потока. Запросы на поток могут относиться как к видео по запросу, так и к прямым трансляциям. В запросах указывается идентификатор контента, а также ключ API или токен аутентификации и другие параметры.
  • StreamManager : объект, который обрабатывает потоки динамической вставки рекламы и взаимодействие с серверной частью DAI. Менеджер потоков также обрабатывает отслеживание пингов и пересылает события потока и рекламы издателю.

Предварительные условия

  • Прочтите нашу страницу совместимости , чтобы убедиться, что ваш предполагаемый вариант использования поддерживается.
  • Загрузите наш пример кода проигрывателя 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

IMA DAI SDK зависит от рекламной платформы Roku. Чтобы загрузить платформу, добавьте следующее в manifest и Sdk.xml :

манифестировать

bs_libs_required=roku_ads_lib,googleima3

Sdk.xml

Library "Roku_Ads.brs"
Library "IMA3.brs"

Загрузите SDK IMA DAI

Первым шагом к загрузке потока динамической вставки объявлений 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 &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

Добавьте поддержку пропускаемых объявлений (необязательно).

Чтобы поддерживать рекламу с возможностью пропуска, необходимо добавить метод seek в объект проигрывателя IMA DAI SDK, который программно ищет видео в указанном месте за секунды с плавающей запятой.

Для поддержки пропускаемой рекламы вы также должны убедиться, что вы установили 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
,

IMA SDK позволяют легко интегрировать мультимедийную рекламу в ваши веб -сайты и приложения. IMA SDK могут запросить рекламу с любого обширного рекламного сервера и управлять воспроизведением рекламы в ваших приложениях. С IMA DAI SDKS приложения делают запрос потока для видео и контента - либо VOD, либо живой контент. Затем SDK возвращает комбинированный видеопоток, так что вам не нужно управлять переключением между видео и контентом в вашем приложении.

Выберите интересное вам решение DAI

Полный сервис Dai

Это руководство демонстрирует, как интегрировать IMA Dai SDK в простое приложение для видеоплеер. Если вы хотите просмотреть или следовать вместе с завершенной выборкой интеграции, загрузите основной пример из GitHub.

Обзор IMA DAI

Реализация IMA DAI включает в себя два основных компонента SDK, как показано в этом руководстве:

  • StreamRequest : объект, который определяет запрос потока. Запросы потока могут быть либо для видео по запросу, либо для живых потоков. Запросы указывают идентификатор контента, а также ключ API или токен аутентификации и другие параметры.
  • StreamManager : объект, который обрабатывает динамические потоки вставки AD и взаимодействия с бэкэнд DAI. Manager Stream также обрабатывает отслеживание пингов и переходных потоков и рекламных событий для издателя.

Предварительные условия

  • Прочитайте нашу страницу совместимости , чтобы убедиться, что ваш предполагаемый вариант использования поддерживается.
  • Загрузите наш пример кода игрока Roku
  • Разверните пример кода игрока на устройство Roku, чтобы убедиться, что ваша разработка работает.

Воспроизвести свое видео

Образец предоставленный видеоплеер воспроизводит видео контента из коробки. Разверните образца игрока в Roku Player, чтобы убедиться, что ваша среда разработки настраивается должным образом.

Превратите свой видеоплеер в Ima Dai Stream Player

Следуйте этим шагам, чтобы реализовать потокового игрока.

Создать 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 DAI SDK зависит от рекламной структуры ROKU. Чтобы загрузить каркас, добавьте следующее в manifest и Sdk.xml :

манифестировать

bs_libs_required=roku_ads_lib,googleima3

Sdk.xml

Library "Roku_Ads.brs"
Library "IMA3.brs"

Загрузите ima dai sdk

Первым шагом к загрузке вашего динамического потока вставки AD 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 Stream

Затем вам нужно использовать существующий roVideoScreen для создания игрока IMA Stream. Этот игровой игрок реализует три метода обратного вызова: 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, но вместо этого вы можете использовать Live, изменив 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 &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

Добавьте поддержку для пропусковкой рекламы (необязательно)

Чтобы поддерживать рекламу, необходимую, вам необходимо добавить метод seek в объект игрока ima dai SDK, который программно ищет видео в указанное место, в сплайт-секундах.

Чтобы поддержать рекламу, вы также должны убедиться, что вы установили 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