البدء

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

تُسهِّل أدوات تطوير البرامج لإعلانات الوسائط التفاعلية دمج إعلانات الوسائط المتعددة في مواقعك الإلكترونية وتطبيقاتك. ويمكن أن تطلب أدوات تطوير البرامج لإعلانات الوسائط التفاعلية إعلانات من أي خادم متوافق مع VAST وإدارة تشغيل الإعلانات في تطبيقاتك. باستخدام حزم تطوير البرامج (SDK) لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية (IMA)، تقدم التطبيقات طلب بث للفيديو ومحتوى الإعلان، سواء كان ذلك من خلال الفيديو المباشر أو المحتوى المباشر. تعرض حزمة تطوير البرامج (SDK) بعد ذلك بث فيديو مجمّعًا، بحيث لا تحتاج إلى إدارة التبديل بين فيديو الإعلان والمحتوى في تطبيقك.

يوضح هذا الدليل كيفية دمج أداة تطوير البرامج (SDK) لإعلانات الوسائط التفاعلية (IMA) في تطبيق بسيط لمشغّل الفيديو. إذا كنت ترغب في مشاهدة عينة من عملية الدمج المكتملة أو متابعتها، يُرجى تنزيل المثال الأساسي من GitHub.

نظرة عامة على DAI لإعلانات الوسائط التفاعلية

يتضمن تنفيذ إعلانات الوسائط التفاعلية (IMA) المكونين الرئيسيين لحزمة تطوير البرامج (SDK) وهما موضحين في هذا الدليل:

  • StreamRequest: كائن يعرّف طلب البث. يمكن أن تكون طلبات البث إما لأحداث الفيديو حسب الطلب أو لأحداث البث المباشر. وتحدد الطلبات معرّف المحتوى، بالإضافة إلى مفتاح واجهة برمجة التطبيقات أو الرمز المميز للمصادقة ومعلمات أخرى.
  • StreamManager: كائن يتعامل مع مجموعات بث إعلان ديناميكي وتفاعلات مع خلفية DAI. كما يتعامل مدير البث أيضًا مع أدوات فحص الاتصال ويعيد توجيه أحداث البث والإعلانات إلى الناشر.

المتطلبات الأساسية

قبل البدء، عليك تنفيذ ما يلي:

  • اطلع على صفحة التوافق للتأكد من أن حالة الاستخدام المقصودة مدعومة.
  • نزّل نموذج شفرة مشغل Roku.
  • انشر نموذج رمز المشغّل أعلاه على جهاز Roku للتحقّق من عمل عملية الإعداد.

تشغيل الفيديو

مشغل نموذج الفيديو الذي تم تقديمه يشغّل محتوى فيديو مباشرةً. انشر نموذج المشغل على مشغل Roku لضمان إعداد بيئة التطوير بشكل صحيح.

تحويل مشغّل الفيديو إلى مشغّل بث إدراجات إعلانات ديناميكية لإعلانات الوسائط التفاعلية

إنشاء ملف 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 الإعلاني

تعتمد أداة تطوير البرامج (SDK) لإعلانات الوسائط التفاعلية (IMA) على إطار عمل إعلانات Roku. لتحميل إطار العمل، أضِف ما يلي إلى manifest وSdk.xml:

البيان
bs_libs_required=roku_ads_lib,googleima3
ملف Sdk.xml
Library "Roku_Ads.brs"
Library "IMA3.brs"

تحميل أداة تطوير البرامج لإعلانات الوسائط التفاعلية

تتمثل الخطوة الأولى لتحميل ساحة مشاركات إدراج الإعلان الديناميكي لإعلانات الوسائط التفاعلية في تحميل أداة تطوير البرامج لإعلانات الوسائط التفاعلية وإعدادها. يعمل ما يلي على تحميل النص البرمجي لأداة تطوير البرامج (SDK) لإعلانات الوسائط التفاعلية (IMA).

ملف 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

إنشاء مشغّل لساحة مشاركات الوسائط التفاعلية

بعد ذلك، عليك استخدام roVideoScreen الحالية لإنشاء مشغّل لساحة مشاركات الوسائط التفاعلية. ينفِّذ مشغِّل البث هذا ثلاث طرق لرد الاتصال: 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
  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
End Sub

إنشاء طلب بث وتنفيذه

الآن بعد أن أصبح لديك مشغل بث، يمكنك إنشاء طلب بث وتنفيذه. يحتوي هذا المثال على بيانات حول البث المباشر وVOD. يتم حاليًا استخدام بث الفيديو المسجّل. لاستخدام ميزة البث المباشر بدلاً من VOD، عليك تغيير selectedStream من m.testVodStream إلى m.testLiveStream.

لكي تتمكّن من دعم 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 = {}
  if m.top.streamData.type = "live"
    request = sdk.CreateLiveStreamRequest(m.top.streamData.assetKey, m.top.streamData.apiKey)
  else if m.top.streamData.type = "vod"
    request = sdk.CreateVodStreamRequest(m.top.streamData.contentSourceId, m.top.streamData.videoId, m.top.streamData.apiKey)
  else
    request = sdk.CreateStreamRequest()
  end if

  request.player = m.player
  request.adUiNode = m.top.video
  request.videoObject = 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