Bắt đầu

IMA SDK giúp dễ dàng tích hợp quảng cáo đa phương tiện vào các trang web và ứng dụng của bạn. SDK IMA có thể yêu cầu quảng cáo từ bất kỳ máy chủ quảng cáo tuân thủ VAST nào và quản lý việc phát quảng cáo trong các ứng dụng của bạn. Với IMA DAI SDK, ứng dụng đưa ra yêu cầu luồng cho quảng cáo và video nội dung—VOD hoặc nội dung trực tiếp. Sau đó, SDK sẽ trả về luồng video kết hợp để bạn không phải quản lý việc chuyển đổi giữa quảng cáo và video nội dung trong ứng dụng của mình.

Hướng dẫn này minh họa cách tích hợp IMA SDK vào một ứng dụng trình phát video đơn giản. Nếu bạn muốn xem hoặc làm theo một bước tích hợp mẫu hoàn chỉnh, hãy tải ví dụ cơ bản xuống từ GitHub.

Tổng quan về IMA DAI

Việc triển khai IMA DAI bao gồm hai thành phần SDK chính, được minh họa trong hướng dẫn này:

  • StreamRequest: Đối tượng xác định yêu cầu luồng. Các yêu cầu phát trực tiếp có thể dành cho video theo yêu cầu hoặc sự kiện phát trực tiếp. Yêu cầu chỉ định ID nội dung, cũng như khóa API hoặc mã thông báo xác thực và các tham số khác.
  • StreamManager: Đối tượng xử lý các luồng chèn quảng cáo động và lượt tương tác với phần phụ trợ DAI. Trình quản lý luồng cũng xử lý các ping theo dõi, đồng thời chuyển tiếp các sự kiện quảng cáo và luồng tới nhà xuất bản.

Điều kiện tiên quyết

Trước khi bắt đầu, bạn cần:

  • Hãy đọc kỹ trang tương thích của chúng tôi để đảm bảo trường hợp sử dụng mà bạn dự định hỗ trợ.
  • Tải xuống mã trình phát mẫu Roku của chúng tôi.
  • Triển khai mã trình phát mẫu ở trên cho thiết bị Roku để xác minh rằng tùy chọn thiết lập bản phát triển của bạn đang hoạt động.

Phát video của bạn

Trình phát video mẫu đã cung cấp sẽ phát video nội dung ngay từ đầu. Triển khai trình phát mẫu cho trình phát Roku để đảm bảo môi trường phát triển của bạn được thiết lập đúng cách.

Chuyển trình phát video của bạn thành trình phát luồng Chèn quảng cáo động IMA

Tạo Sdk.xml

Thêm một tệp mới vào dự án của bạn cùng với MainScene.xml có tên là Sdk.xml rồi thêm mẫu soạn sẵn sau đây:

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>

Bạn cần chỉnh sửa cả hai tệp này trong suốt hướng dẫn này. Một tiêu đề phía trên mỗi đoạn mã sẽ cho biết bạn cần thêm đoạn mã đó vào tệp nào.

Tải Khung quảng cáo Roku

IMA SDK phụ thuộc vào Khung quảng cáo Roku. Để tải khung này, hãy thêm nội dung sau vào manifestSdk.xml:

manifest
bs_libs_required=roku_ads_lib,googleima3
Sdk.xml
Library "Roku_Ads.brs"
Library "IMA3.brs"

Tải IMA SDK

Bước đầu tiên để tải luồng Chèn quảng cáo động IMA là tải và khởi chạy SDK IMA. Thao tác sau sẽ tải tập lệnh 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

Bây giờ, hãy bắt đầu tác vụ này trong MainScene.xml và xoá lệnh gọi để tải luồng nội dung.

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

Tạo trình phát luồng IMA

Tiếp theo, bạn cần sử dụng roVideoScreen hiện có để tạo trình phát luồng IMA. Trình phát luồng này triển khai ba phương thức gọi lại: loadUrl, adBreakStartedadBreakEnded. Đồng thời tắt thủ thuật phát lừa khi luồng được tải. Điều này ngăn người dùng bỏ qua một quảng cáo trước video ngay khi bắt đầu, trước khi sự kiện ngắt quảng cáo bắt đầu được kích hoạt.

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

Tạo và thực thi một yêu cầu luồng

Bây giờ khi đã có trình phát luồng, bạn có thể tạo và thực thi một yêu cầu luồng. Ví dụ này có dữ liệu cho một luồng trực tiếp và một luồng VOD. Hiện đang sử dụng luồng VOD. Để sử dụng sự kiện trực tiếp thay vì VOD, hãy thay đổi selectedStream từ m.testVodStream thành m.testLiveStream.

Để có thể hỗ trợ AdUI, chẳng hạn như các biểu tượng adChoices, bạn cũng phải chuyển thông tin tham chiếu đến nút chứa video nội dung trong yêu cầu của mình.

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

Thêm trình xử lý sự kiện và bắt đầu luồng

Sau khi yêu cầu sự kiện trực tiếp, bạn chỉ còn một vài việc cần làm: thêm trình xử lý sự kiện để theo dõi tiến trình quảng cáo, bắt đầu sự kiện trực tiếp và chuyển tiếp thông báo Roku đến SDK. Điều vô cùng quan trọng là bạn phải chuyển tiếp tất cả thông báo đến SDK để đảm bảo phát lại quảng cáo chính xác.

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

Thêm tùy chọn hỗ trợ cho quảng cáo có thể bỏ qua (không bắt buộc)

Để hỗ trợ quảng cáo có thể bỏ qua, bạn cần thêm một phương thức seek vào đối tượng trình phát của SDK IMA để tìm kiếm video theo vị trí được chỉ định, theo dấu phẩy động.

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

  ...