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

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

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

عرض الإعلانات المتسلسلة التي تتضمّن ميزة DAI

يشرح هذا الدليل كيفية تشغيل بث عرض مجموعة الإعلانات الديناميكية على شبكة البحث للمحتوى المباشر أو المسجّل، باستخدام حزمة تطوير البرامج لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية بتنسيق HTML5 مع مشغّل فيديو يعتمد على التنسيق hls.js للتشغيل. إذا كنت تريد عرض أو متابعة نموذج دمج مكتمل مع إمكانية تشغيل HLS.js وSafari، اطّلِع على مثال على عرض مجموعات HLS. بالنسبة إلى دعم DASH.js، راجع مثال عرض لوحة DASH. يمكنك تنزيل نماذج التطبيقات هذه من صفحة إصدار HTML5 DAI GitHub.

نظرة عامة على عرض لوحة DAI

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

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

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

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

قبل البدء، تحتاج إلى ما يلي:

  • ثلاثة ملفات فارغة:

    • dai.html
    • dai.css
    • dai.js
  • لغة Python مثبتة على جهاز الكمبيوتر أو خادم ويب أو بيئة تطوير مستضافة أخرى لاستخدامها في الاختبار

ضبط بيئة تطوير

وبما أنّ حزمة SDK تُحمِّل التبعيات باستخدام البروتوكول نفسه المستخدَم في الصفحة التي تمّ تحميلها منه، عليك استخدام خادم ويب لاختبار تطبيقك. وأبسط طريقة لبدء خادم تطوير محلي هي استخدام خادم Python المدمج.

  1. باستخدام سطر الأوامر، من الدليل الذي يتضمّن ملف index.html، اتّبِع الخطوات التالية:

    python -m http.server 8000
    
  2. في متصفّح ويب، انتقِل إلى http://localhost:8000/.

    يمكنك أيضًا استخدام أي بيئة تطوير مستضافة أو خادم ويب آخر، مثل Apache HTTP Server.

إنشاء مشغّل فيديو بسيط

أولاً، عدِّل dai.html لإنشاء عنصر فيديو HTML5 بسيط، مع عنصر div لاستخدامه لعناصر واجهة المستخدم في الإعلان. أضِف أيضًا العلامات اللازمة لتحميل ملفَّي dai.css وdai.js، بالإضافة إلى استيراد مشغّل الفيديو hls.js.

بعد ذلك، عدِّل dai.css لتحديد حجم عناصر الصفحة وموضعها. أخيرًا، في dai.js، حدِّد المتغيّرات للاحتفاظ بمعلومات طلب البث والدالة initPlayer() لتشغيلها عند تحميل الصفحة.

ثوابت طلب البث هي كما يلي:

  • BACKUP_STREAM: عنوان URL لبثّ احتياطي يتم تشغيله في حال حدوث خطأ جسيم في عملية عرض الإعلانات

  • STREAM_URL: يُستخدَم هذا الخيار في أحداث البث المباشر فقط. عنوان URL لبث الفيديو الذي قدمه مناور البيان أو الشريك الخارجي الذي يستخدم عرض الإعلانات المتسلسلة. وسيتطلّب منك ذلك إدراج معرّف مصدر البيانات الذي توفّره حزمة تطوير البرامج لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية قبل تقديم الطلب. في هذه الحالة، يشتمل عنوان URL الخاص بمصدر البيانات على عنصر نائب [[STREAMID]]، يتم استبداله بمعرّف مصدر البيانات قبل تقديم طلب.

  • NETWORK_CODE: رمز الشبكة لحسابك على "مدير الإعلانات 360".

  • CUSTOM_ASSET_KEY: يُستخدَم هذا الخيار في أحداث البث المباشر فقط. مفتاح مادة العرض المخصّص الذي يحدّد حدث عرض الإعلانات المتسلسلة في "مدير الإعلانات 360" يمكن إنشاء ذلك من خلال أداة معالجة البيان أو شريك عرض الإعلانات المتسلسلة التابعة لجهة خارجية.

  • API_KEY: يُستخدَم هذا الخيار في أحداث البث المباشر فقط. مفتاح واجهة برمجة تطبيقات اختياري يمكن أن يكون مطلوبًا لاسترداد رقم تعريف مصدر البيانات من حزمة تطوير البرامج لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
  <h2>IMA DAI SDK Demo (HLS.JS)</h2>
    <video id="video"></video>
    <div id="ad-ui"></div>
</body>
</html>

dai.css

#video,
#ad-ui {
  width: 640px;
  height: 360px;
  position: absolute;
  top: 35px;
  left: 0;
}

#ad-ui {
  cursor: pointer;
}

dai.js

var BACKUP_STREAM =
    'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'

// Stream Config.
const STREAM_URL = "https://encodersim.sandbox.google.com/masterPlaylist/...&stream_id=[[STREAMID]]";
const NETWORK_CODE = "51636543";
const CUSTOM_ASSET_KEY = "google-sample";
const API_KEY = "";

var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
}

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

بعد ذلك، أضِف إطار عمل DAI باستخدام علامة نص برمجي في dai.html، قبل علامة dai.js.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
...

إعداد StreamManager وتقديم طلب بث مباشر أو فيديو عند الطلب

عرض مجموعات البث المباشر

لطلب مجموعة من الإعلانات، عليك إنشاء ima.dai.api.StreamManager، وهي مسؤولة عن طلب عمليات بث DAI وإدارتها. تأخذ الدالة الإنشائية عنصر فيديو ويأخذ المثيل الناتج عنصر واجهة مستخدم الإعلان للتعامل مع التفاعلات مع الإعلان.

بعد ذلك، حدِّد دالة لطلب البث المباشر الذي يعرض مجموعة الإعلانات المتسلسلة. تنشئ هذه الدالة أولاً PodStreamRequest، وتضبطه باستخدام معلمات StreamRequest الواردة في الخطوة 2، ثم تستدعي streamManager.requestStream() باستخدام كائن الطلب هذا.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestLivePodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}

function requestLivePodStream(networkCode, customAssetKey, apiKey) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving live Stream Request
  const streamRequest = new google.ima.dai.api.PodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.customAssetKey = customAssetKey;
  streamRequest.apiKey = apiKey;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

عرض إعلانات متسلسلة عند الطلب

لطلب مجموعة من الإعلانات، عليك إنشاء ima.dai.api.StreamManager، وهي مسؤولة عن طلب عمليات بث DAI وإدارتها. تأخذ الدالة الإنشائية عنصر فيديو ويأخذ المثيل الناتج عنصر واجهة مستخدم الإعلان للتعامل مع التفاعلات مع الإعلان.

بعد ذلك، حدِّد دالة لطلب بث الفيديو عند الطلب الذي يعرض مجموعة الإعلانات المتسلسلة. تنشئ هذه الدالة أولاً PodVodStreamRequest، وتضبطه باستخدام معلمات StreamRequest الواردة في الخطوة 2، ثم تستدعي streamManager.requestStream() باستخدام كائن الطلب هذا.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestVodPodStream(NETWORK_CODE);
}

function requestVodPodStream(networkCode) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving VOD Stream Request
  const streamRequest = new google.ima.dai.api.PodVodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

معالجة أحداث البث

عرض مجموعات البث المباشر

بعد ذلك، نفِّذ أدوات معالجة الأحداث لأحداث الفيديو الرئيسية. يعالج هذا المثال الأحداث STREAM_INITIALIZED وERROR وAD_BREAK_STARTED وAD_BREAK_ENDED من خلال استدعاء دالة onStreamEvent(). تتعامل هذه الوظيفة مع عمليات تحميل البث والأخطاء، بالإضافة إلى إيقاف عناصر التحكم في المشغّل أثناء عرض إعلان، وهو ما تتطلبه حزمة تطوير البرامج (SDK). عند تحميل مجموعة البث، يتم تحميل مشغّل الفيديو وتشغيل عنوان URL المقدَّم باستخدام دالة loadStream().

dai.js

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      console.log('Stream initialized');
      loadStream(e.getStreamData().streamId);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream('');
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(streamID) {
  var url;
  if(streamID) {
    url = STREAM_URL.replace('[[STREAMID]]', streamID);
  } else {
    console.log('Stream Initialization Failed');
    url = BACKUP_STREAM;
  }
  console.log('Loading:' + url);
  hls.loadSource(url);
  hls.attachMedia(videoElement);
}

عرض إعلانات متسلسلة عند الطلب

بعد ذلك، نفِّذ أدوات معالجة الأحداث لأحداث الفيديو الرئيسية. يعالج هذا المثال الأحداث STREAM_INITIALIZED وLOADED وERROR وAD_BREAK_STARTED وAD_BREAK_ENDED من خلال استدعاء دالة onStreamEvent(). وتعالج هذه الوظيفة تحميل البث والأخطاء، بالإضافة إلى إيقاف عناصر التحكم في المشغّل أثناء عرض إعلان، وهو ما تتطلبه حزمة تطوير البرامج (SDK).

بالإضافة إلى ذلك، تتطلّب أحداث عرض مجموعات الفيديوهات عند الطلب طلب إرسال الرمز StreamManager.loadStreamMetadata() استجابةً لحدث STREAM_INITIALIZED. يجب أيضًا طلب عنوان URL للبث من شريك تقنية الفيديو (VTP). بعد نجاح طلب loadStreamMetadata()، يتم بدء حدث LOADED، حيث يجب استدعاء الدالة loadStream() مع عنوان URL للبث لتحميل البث وتشغيله.

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      const streamId = e.getStreamData().streamId;
      // 'vtpInterface' is a place holder for your own video technology
      //  partner (VTP) API calls.
      vtpInterface.requestStreamURL({
        'streamId': streamId,
      })
      .then( (vtpStreamUrl) => {
        streamUrl = vtpStreamUrl;
        streamManager.loadStreamMetadata();
      }, (error) => {
        // Handle the error.
      });
      break;
    case google.ima.dai.api.StreamEvent.Type.LOADED:
      loadStream(streamUrl);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream();
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(url) {
  if(url) {
    console.log('Loading:' + url);
    hls.loadSource(url);
  } else {
    console.log('Stream Initialization Failed');
    hls.loadSource(BACKUP_STREAM);
  }
  hls.attachMedia(videoElement);
}

البيانات الوصفية للبث المباشر

في هذه الخطوة، يتم تنفيذ أدوات معالجة الأحداث للبيانات الوصفية من أجل إشعار حزمة تطوير البرامج (SDK) عند وقوع أحداث إعلانية. قد يختلف الاستماع إلى أحداث البيانات الوصفية أثناء البث بناءً على تنسيق البث (HLS أو DASH) ونوع البث (بث مباشر أو فيديو عند الطلب) ونوع المشغّل ونوع خلفية DAI المستخدَمة. راجع دليل البيانات الوصفية ذات الوقت لمزيد من المعلومات.

تنسيق البث HLS (أحداث البث المباشر والفيديوهات عند الطلب، مشغّل HLS.js)

إذا كنت تستخدم مشغِّل HLS.js، استمع إلى حدث HLS.js FRAG_PARSING_METADATA للحصول على البيانات الوصفية من ID3 وتمريرها إلى حزمة تطوير البرامج (SDK) باستخدام StreamManager.processMetadata().

لتشغيل الفيديو تلقائيًا بعد أن يتم تحميل الفيديو وجاهزيته، استمِع إلى حدث HLS.js MANIFEST_PARSED لبدء التشغيل.

function loadStream(streamID) {
  hls.loadSource(url);
  hls.attachMedia(videoElement);
  
  // Timed metadata is passed HLS stream events to the streamManager.
  hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
  hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
}

function parseID3Events(event, data) {
  if (streamManager && data) {
    // For each ID3 tag in the metadata, pass in the type - ID3, the
    // tag data (a byte array), and the presentation timestamp (PTS).
    data.samples.forEach((sample) => {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
}

function startPlayback() {
  console.log('Video Play');
  videoElement.play();
}

DASH.js (تنسيق أحداث البث DASH، نوع البث المباشر والفيديوهات عند الطلب)

إذا كنت تستخدم مشغِّل DASH.js، عليك استخدام سلاسل مختلفة للاستماع إلى بيانات ID3 الوصفية لأحداث البث المباشر أو الفيديوهات عند الطلب:

  • أحداث البث المباشر: 'https://developer.apple.com/streaming/emsg-id3'
  • عدد مشاهدات الفيديوهات عند الطلب: 'urn:google:dai:2018'

مرِّر البيانات الوصفية من ID3 إلى حزمة تطوير البرامج (SDK) باستخدام StreamManager.processMetadata().

لعرض عناصر التحكّم في الفيديو تلقائيًا بعد تحميل كل العناصر وجاهزيتها، استمِع إلى حدث MANIFEST_LOADED على DASH.js.

const googleLiveSchema = 'https://developer.apple.com/streaming/emsg-id3';
const googleVodSchema = 'urn:google:dai:2018';
dashPlayer.on(googleLiveSchema, processMetadata);
dashPlayer.on(googleVodSchema, processMetadata);
dashPlayer.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);

function processMetadata(metadataEvent) {
  const messageData = metadataEvent.event.messageData;
  const timestamp = metadataEvent.event.calculatedPresentationTime;

  // Use StreamManager.processMetadata() if your video player provides raw
  // ID3 tags, as with dash.js.
  streamManager.processMetadata('ID3', messageData, timestamp);
}

function loadlistener() {
  showControls();

  // This listener must be removed, otherwise it triggers as addional
  // manifests are loaded. The manifest is loaded once for the content,
  // but additional manifests are loaded for upcoming ad breaks.
  dashPlayer.off(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
}

Shaka Player مع أحداث بث مباشر (تنسيق أحداث البث DASH)

إذا كنت تستخدم Shaka Player لتشغيل البث المباشر، استخدِم السلسلة 'emsg' للاستماع إلى أحداث البيانات الوصفية. بعد ذلك، استخدِم بيانات رسالة الحدث في مكالمتك على الرقم StreamManager.onTimedMetadata().

shakaPlayer.addEventListener('emsg', (event) => onEmsgEvent(event));

function onEmsgEvent(metadataEvent) {
  // Use StreamManager.onTimedMetadata() if your video player provides
  // processed metadata, as with Shaka player livestreams.
  streamManager.onTimedMetadata({'TXXX': metadataEvent.detail.messageData});
}

Shaka Player مع فيديوهات متوفرة عند الطلب (تنسيق DASH)

إذا كنت تستخدم Shaka Player لتشغيل بث الفيديو عند الطلب، استخدِم السلسلة 'timelineregionenter' للاستماع إلى أحداث البيانات الوصفية. بعد ذلك، استخدِم بيانات رسالة الحدث في الطلب StreamManager.processMetadata() مع السلسلة 'urn:google:dai:2018'.

shakaPlayer.addEventListener('timelineregionenter', (event) => onTimelineEvent(event));

function onTimelineEvent(metadataEvent) {
  const detail = metadataEvent.detail;
  if ( detail.eventElement.attributes &&
       detail.eventElement.attributes['messageData'] &&
       detail.eventElement.attributes['messageData'].value ) {
        const mediaId = detail.eventElement.attributes['messageData'].value;
        const pts = detail.startTime;
        // Use StreamManager.processMetadata() if your video player provides raw
        // ID3 tags, as with Shaka player VOD streams.
        streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
       }
}

التعامل مع أحداث اللاعبين

يمكنك إضافة أدوات معالجة الأحداث إلى الحدثَين pause وstart لعنصر الفيديو للسماح للمستخدم باستئناف التشغيل عند توقُّف حزمة تطوير البرامج (SDK) مؤقتًا أثناء الفواصل الإعلانية.

function loadStream(streamUrl) {
  ...
  
  videoElement.addEventListener('pause', onStreamPause);
  videoElement.addEventListener('play', onStreamPlay);
}

function onStreamPause() {
  console.log('paused');
  if (isAdBreak) {
    videoElement.controls = true;
    adUiElement.style.display = 'none';
  }
}

function onStreamPlay() {
  console.log('played');
  if (isAdBreak) {
    videoElement.controls = false;
    adUiElement.style.display = 'block';
  }
}

أكملت هذه الخطوة. أنت الآن تطلب الإعلانات وتعرضها في سلسلة إعلانات متسلسلة باستخدام حزمة تطوير البرامج لإدراج إعلان ديناميكي لإعلانات الوسائط التفاعلية لـ HTML5. لمعرفة المزيد من الميزات المتقدمة لحِزم SDK، يمكنك الاطّلاع على الأدلة الأخرى أو النماذج المتوفّرة على GitHub.