بدء استخدام حزمة تطوير البرامج لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية

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

اختيار حل DAI الذي يهمّك

إدراج إعلان ديناميكي لخدمة كاملة

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

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

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

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

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

  • يُرجى الاطّلاع على صفحة التوافق للتأكد من توافق حالة الاستخدام التي تريدها.
  • نزِّل نموذج رمز مشغّل 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 الإعلاني

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

بيان

bs_libs_required=roku_ads_lib,googleima3

Sdk.xml

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

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

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

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
End Sub

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

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

ولدعم AdUI، مثل رموز "خيارات الإعلان"، عليك أيضًا تمرير مرجع إلى العقدة التي تحتوي على فيديو المحتوى كجزء من طلبك.

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 إلى كائن مشغّل أداة تطوير البرامج لإعلانات الوسائط التفاعلية الذي ينقل الفيديو آليًا إلى الموقع المحدّد، خلال ثوانٍ عائمة.

لإتاحة الإعلانات القابلة للتخطّي، عليك أيضًا التأكّد من ضبط السمة 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