يوضّح هذا الدليل كيفية تشغيل بث "عرض الإعلانات في مجموعات" من خلال ميزة "إدراج الإعلان الديناميكي" لمحتوى مباشر أو محتوى فيديو عند الطلب، وذلك باستخدام حزمة تطوير البرامج (SDK) لتقنية "إدراج الإعلان الديناميكي" في "إعلانات الوسائط التفاعلية" (IMA) في HTML5 مع مشغّل فيديو يعتمد على hls.js للتشغيل. للاطّلاع على نموذج دمج مكتمل أو اتّباعه، مع إتاحة كلّ من HLS.js وSafari Playback، يمكنك الاطّلاع على مثال عرض مجموعة إعلانات HLS. للحصول على دعم DASH.js، يُرجى الاطّلاع على مثال عرض مجموعة إعلانية متسلسلة في DASH. يمكنك تنزيل نماذج التطبيقات هذه من صفحة إصدار HTML5 DAI على GitHub.
نظرة عامة على ميزة "عرض مجموعة إعلانات" في "إدراج الإعلانات الديناميكية"
يتضمّن تنفيذ ميزة "عرض الإعلانات في مجموعات" باستخدام حزمة تطوير البرامج (SDK) لتقنية "إدراج الإعلان الديناميكي" في "إعلانات الوسائط التفاعلية" مكوّنَين رئيسيَّين، وهما موضّحان في هذا الدليل:
PodStreamRequest/PodVodStreamRequest: عنصر يحدّد طلب بث إلى خوادم Google الإعلانية. تحدّد الطلبات رمز شبكة، وتتطلّبPodStreamRequestأيضًا مفتاح مادة عرض مخصّص ومفتاح واجهة برمجة تطبيقات اختياري. ويتضمّن كلاهما مَعلمات اختيارية أخرى.StreamManager: عنصر يعالج الاتصال بين بث الفيديو وحزمة تطوير البرامج (SDK) لتقنية IMA DAI، مثل تنشيط إشعارات التتبّع وإعادة توجيه أحداث البث إلى الناشر.
المتطلبات الأساسية
قبل البدء، تحتاج إلى ما يلي:
ثلاثة ملفات فارغة:
- dai.html
- dai.css
- dai.js
تثبيت Python على جهاز الكمبيوتر أو خادم ويب أو بيئة تطوير أخرى مستضافة لاستخدامها في الاختبار
ضبط بيئة تطوير
بما أنّ حزمة تطوير البرامج (SDK) تحمّل التبعيات باستخدام البروتوكول نفسه الذي تستخدمه الصفحة التي يتم تحميلها منها، عليك استخدام خادم ويب لاختبار تطبيقك. يمكنك بدء تشغيل خادم تطوير محلي بسرعة من خلال استخدام خادم Python المضمّن.
باستخدام سطر أوامر، من الدليل الذي يحتوي على ملف
index.html، نفِّذ ما يلي:python -m http.server 8000في متصفّح الويب، انتقِل إلى
http://localhost:8000/يمكنك أيضًا استخدام أي بيئة تطوير أو خادم ويب آخر مستضاف، مثل خادم Apache HTTP.
إنشاء مشغّل فيديو
أولاً، عدِّل dai.html لإنشاء عنصر فيديو HTML5 وعنصر div
لاستخدامهما في عناصر واجهة مستخدم الإعلانات. أضِف أيضًا العلامات اللازمة لتحميل ملفَي dai.css وdai.js، بالإضافة إلى استيراد مشغّل الفيديو hls.js.
بعد ذلك، عدِّل ملف dai.css لتحديد حجم عناصر الصفحة وموضعها.
أخيرًا، في dai.js، حدِّد المتغيّرات للاحتفاظ بمعلومات طلب البث
ودالة initPlayer() لتشغيلها عند تحميل الصفحة.
في ما يلي ثوابت طلبات البث:
BACKUP_STREAM: عنوان URL لبث احتياطي يتم تشغيله في حال حدوث خطأ فادح في عملية عرض الإعلانات
STREAM_URL: يُستخدَم فقط لأحداث البث المباشر. عنوان URL لبث الفيديو الذي يوفّره مُعدِّل البيان أو الشريك الخارجي باستخدام ميزة "عرض الإعلانات في مجموعات" يجب أن يتطلب منك إدخال معرّف البث الذي توفّره حزمة تطوير البرامج (SDK) لعرض إعلانات الوسائط التفاعلية (IMA) لإدراج الإعلانات الديناميكية (DAI)، قبل تقديم طلب. في هذه الحالة، يتضمّن عنوان URL للبث عنصرًا نائبًا،[[STREAMID]]، يتم استبداله بمعرّف البث قبل تقديم الطلب.
NETWORK_CODE: رمز الشبكة لحسابك على "إدارة إعلانات Google 360"
CUSTOM_ASSET_KEY: يُستخدَم فقط لأحداث البث المباشر. مفتاح مادة العرض المخصّصة الذي يحدّد حدث عرض الإعلانات في مجموعات في "مدير إعلانات Google 360" ويمكن إنشاء هذه القيمة من خلال أداة معالجة البيان أو شريك عرض الإعلانات في مجموعات التابع لجهة خارجية.
API_KEY: يُستخدَم فقط لأحداث البث المباشر. مفتاح واجهة برمجة تطبيقات اختياري يمكن أن يكون مطلوبًا لاسترداد معرّف بث من حزمة تطوير البرامج (SDK) لـ IMA DAI.
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="adUi"></div>
</body>
</html>
dai.css
#video,
#adUi {
width: 640px;
height: 360px;
position: absolute;
top: 35px;
left: 0;
}
#adUi {
cursor: pointer;
}
dai.js
var BACKUP_STREAM =
'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'
// Stream Config.
const STREAM_URL = "";
const NETWORK_CODE = "";
const CUSTOM_ASSET_KEY = "";
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');
}
تحميل حزمة تطوير البرامج (SDK) لتقنية IMA 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، وهو المسؤول عن طلب وإدارة أحداث البث المباشر لإدراج الإعلانات ديناميكيًا. تتلقّى الدالة الإنشائية عنصر فيديو، ويتلقّى المثيل الناتج عنصرًا في واجهة المستخدم للإعلان من أجل معالجة التفاعلات مع الإعلان.
بعد ذلك، حدِّد دالة لطلب البث المباشر من خلال ميزة "عرض الإعلانات في مجموعات". تنشئ هذه الدالة أولاً كائن 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، وهو المسؤول عن طلب وإدارة أحداث البث المباشر لإدراج الإعلانات ديناميكيًا. تتلقّى الدالة الإنشائية عنصر فيديو، ويتلقّى المثيل الناتج عنصرًا في واجهة المستخدم للإعلان من أجل معالجة التفاعلات مع الإعلان.
بعد ذلك، حدِّد دالة لطلب بث الفيديو عند الطلب من خلال ميزة "عرض الإعلانات في مجموعات". تنشئ هذه الدالة أولاً كائن 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) ونوع البث (بث مباشر أو فيديو عند الطلب) ونوع المشغّل ونوع الخلفية المستخدَمة في ميزة "إدراج الإعلان ديناميكيًا". لمزيد من المعلومات، يُرجى الاطّلاع على دليل البيانات الوصفية المحدّدة زمنيًا.
تنسيق بث HLS (أحداث البث المباشر والفيديوهات عند الطلب، مشغّل HLS.js)
إذا كنت تستخدم مشغّل HLS.js، استمِع إلى حدث HLS.js FRAG_PARSING_METADATA للحصول على بيانات ID3 الوصفية وإرسالها إلى حزمة تطوير البرامج (SDK) باستخدام StreamManager.processMetadata().
لتشغيل الفيديو تلقائيًا بعد تحميل كل المحتوى وتجهيزه، يمكنك الاستماع إلى الحدث MANIFEST_PARSED في HLS.js لتشغيل الفيديو.
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().
لعرض عناصر التحكّم في الفيديو تلقائيًا بعد تحميل كل المحتوى وجاهزيته،
يمكنك الاستماع إلى حدث DASH.js MANIFEST_LOADED.
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 لتشغيل البث المباشر، استخدِم السلسلة '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 لتشغيل
بث الفيديو عند الطلب، استخدِم السلسلة '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';
}
}
حذف مواد عرض IMA DAI
عند الانتهاء بنجاح من طلب الإعلانات وعرضها في بث عرض الإعلانات المتعدّدة باستخدام حزمة تطوير البرامج (SDK) لعرض الإعلانات الديناميكي (DAI) في "إعلانات الوسائط التفاعلية" (IMA)، ننصحك بإزالة أي موارد بعد اكتمال جلسة عرض الإعلانات المتعدّدة. يمكنك استدعاء StreamManager.destroy() لإيقاف تشغيل البث وإيقاف تتبُّع الإعلانات وإصدار جميع مواد عرض البث التي تم تحميلها.
لمزيد من المعلومات حول ميزات حزمة تطوير البرامج (SDK) الأكثر تقدّمًا، يُرجى الاطّلاع على الأدلة الأخرى أو النماذج على GitHub.