Как настроить IMA SDK для динамической вставки объявлений

Выберите платформу: HTML5 Android iOS tvOS Cast Roku

IMA SDK позволяет легко интегрировать мультимедийные объявления на сайты и в приложения. IMA SDK может запрашивать объявления с любого совместимого с VAST сервера объявлений и управлять воспроизведением рекламы в ваших приложениях. С помощью IMA DAI SDK приложения отправляют запрос потока для видеообъявления и контента (видео по запросу или трансляции). Затем SDK возвращает комбинированный видеопоток, поэтому вам не нужно управлять переключением между рекламой и контентом в приложении.

Выберите решение для динамической вставки объявлений

Показ пакетов с динамической вставкой объявлений

В этом руководстве рассказывается, как воспроизводить поток с динамической вставкой объявлений для прямых трансляций или видео по запросу, используя IMA DAI SDK для HTML5 с видеопроигрывателем, который полагается на hls.js для воспроизведения. Чтобы посмотреть или использовать готовую интеграцию с поддержкой HLS.js и воспроизведения в Safari, ознакомьтесь с примером показа пакета HLS. Информацию о поддержке DASH.js можно найти в примере показа пакетов с динамической вставкой объявлений в DASH. Скачать эти примеры приложений можно на странице выпуска HTML5 DAI на GitHub.

Общие сведения о показе пакетов с динамической вставкой объявлений

В этом руководстве рассказывается о двух основных компонентах, необходимых для реализации показа пакетов с помощью IMA DAI SDK:

  • PodStreamRequest / PodVodStreamRequest: объект, определяющий запрос потока к рекламным серверам Google. В запросах указывается код сети, а для PodStreamRequest также требуется специальный ключ объекта и необязательный ключ API. Оба варианта включают другие необязательные параметры.

  • StreamManager – объект, который обрабатывает связь между видеопотоком и IMA DAI SDK, например отправляет пинги отслеживания и пересылает события потока издателю.

Требования

Прежде чем начать, вам понадобится следующее:

  • Три пустых файла:

    • 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 видеопотока, предоставленный вашим инструментом управления манифестом или внешним партнером, который использует показ пакетов. Вам нужно будет вставить идентификатор трансляции, предоставленный IMA DAI SDK, прежде чем отправлять запрос. В этом случае URL трансляции содержит плейсхолдер [[STREAMID]], который заменяется на идентификатор трансляции перед отправкой запроса.

  • NETWORK_CODE – код сети для вашего аккаунта Менеджера рекламы 360.

  • CUSTOM_ASSET_KEY: используется только для прямых трансляций. Специальный ключ объекта, который идентифицирует событие показа пакета в Менеджере кампаний 360. Его может создать ваш инструмент управления манифестом или сторонний партнер по показу пакетов.

  • API_KEY: используется только для прямых трансляций. Необязательный ключ API, который может потребоваться для получения идентификатора потока из IMA DAI SDK.

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');
}

Загрузка IMA DAI SDK

Затем добавьте фреймворк DAI с помощью тега script в 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. Конструктор принимает видеоэлемент, а полученный экземпляр – элемент интерфейса объявления для обработки взаимодействий с рекламой.

Затем определите функцию для запроса потока VOD с показом пакетов. Эта функция сначала создает объект 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.

Кроме того, для потоков VOD Pod Serving требуется вызывать StreamManager.loadStreamMetadata() в ответ на событие STREAM_INITIALIZED. Вам также нужно запросить URL стрима у партнера по видеотехнологиям. После успешного вызова 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, прослушайте событие FRAG_PARSING_METADATA HLS.js, чтобы получить метаданные 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, типы трансляций: прямая и VOD)

Если вы используете проигрыватель DASH.js, то для прослушивания метаданных ID3 в прямых трансляциях и видео по запросу вам нужно использовать разные строки:

  • Прямые трансляции: 'https://developer.apple.com/streaming/emsg-id3'
  • Трансляции VOD: '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';
  }
}

Как удалить объекты IMA DAI

После того как вы успешно запросите и покажете объявления в потоке с показом пакетов объявлений с помощью IMA DAI SDK, мы рекомендуем очистить все ресурсы после завершения сеанса показа пакетов объявлений. Вызовите StreamManager.destroy(), чтобы остановить воспроизведение потока, прекратить отслеживание рекламы и освободить все загруженные объекты потока.

Чтобы узнать больше о расширенных функциях SDK, ознакомьтесь с другими руководствами или примерами на GitHub.