Configurar com a DAI de veiculação de conjunto

Selecione a plataforma: HTML5 Android iOS tvOS Cast Roku

Este guia demonstra como reproduzir um stream de veiculação de conjunto DAI para conteúdo ao vivo ou VOD usando o SDK da DAI do IMA para HTML5 com um player de vídeo que usa hls.js para reprodução. Para conferir ou seguir um exemplo de integração concluída, com suporte para HLS.js e reprodução do Safari, consulte o exemplo de veiculação de conjunto de anúncios HLS. Para suporte ao DASH.js, consulte o exemplo de veiculação de conjunto DASH. Você pode baixar esses apps de exemplo na página de lançamento do DAI HTML5 no GitHub.

Visão geral da veiculação de pods DAI

A implementação da veiculação de conjunto usando o SDK de DAI do IMA envolve dois componentes principais, que são demonstrados neste guia:

  • PodStreamRequest / PodVodStreamRequest: um objeto que define uma solicitação de stream para os servidores de publicidade do Google. As solicitações especificam um código de rede, e o PodStreamRequest também exige uma chave de recurso personalizada e uma chave de API opcional. Ambos incluem outros parâmetros opcionais.

  • StreamManager: um objeto que processa a comunicação entre o stream de vídeo e o SDK de DAI do IMA, como disparar pings de rastreamento e encaminhar eventos de stream para o publisher.

Pré-requisitos

Antes de começar, os seguintes itens são necessários:

  • Três arquivos vazios:

    • dai.html
    • dai.css
    • dai.js
  • Python instalado no computador, um servidor da Web ou outro ambiente de desenvolvimento hospedado para usar em testes

Configurar um ambiente de desenvolvimento

Como o SDK carrega dependências usando o mesmo protocolo da página em que é carregado, você precisa usar um servidor da Web para testar seu app. Uma maneira rápida de iniciar um servidor de desenvolvimento local é usar o servidor integrado do Python.

  1. Usando uma linha de comando, no diretório que contém o arquivo index.html, execute:

    python -m http.server 8000
  2. Em um navegador da Web, acesse http://localhost:8000/.

    Também é possível usar qualquer outro ambiente de desenvolvimento hospedado ou servidor da Web, como o servidor HTTP Apache.

Criar um player de vídeo

Primeiro, modifique dai.html para criar um elemento de vídeo HTML5 e uma div para usar nos elementos da interface do anúncio. Adicione também as tags necessárias para carregar os arquivos dai.css e dai.js, além de importar o player de vídeo hls.js.

Em seguida, modifique dai.css para especificar o tamanho e a posição dos elementos da página. Por fim, em dai.js, defina variáveis para armazenar as informações da solicitação de stream e uma função initPlayer() para ser executada quando o carregamento de página.

As constantes de solicitação de stream são as seguintes:

  • BACKUP_STREAM: um URL para uma transmissão de backup que será reproduzida caso o processo de anúncios encontre um erro fatal.

  • STREAM_URL: usado apenas para transmissões ao vivo. O URL do stream de vídeo fornecido pelo seu manipulador de manifesto ou parceiro terceirizado usando a veiculação de conjunto. Ele deve exigir que você insira o ID do stream fornecido pelo SDK de DAI do IMA antes de fazer uma solicitação. Nesse caso, o URL do stream inclui um marcador de posição, [[STREAMID]], que é substituído pelo ID do stream antes de fazer uma solicitação.

  • NETWORK_CODE: o código de rede da sua conta do Ad Manager 360.

  • CUSTOM_ASSET_KEY: usado apenas para transmissões ao vivo. A chave de recurso personalizada que identifica o evento de veiculação de pod no Ad Manager 360. Ele pode ser criado pelo seu manipulador de manifesto ou parceiro terceirizado de veiculação de conjunto.

  • API_KEY: usado apenas para transmissões ao vivo. Uma chave de API opcional que pode ser necessária para recuperar um ID de stream do SDK de DAI do IMA.

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

Carregar o SDK de DAI do IMA

Em seguida, adicione o framework de DAI usando uma tag script em dai.html, antes da tag para 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>
...

Inicializar o StreamManager e fazer uma solicitação de transmissão ao vivo ou VOD

Disponibilização de pods de transmissão ao vivo

Para solicitar um conjunto de anúncios, crie um ima.dai.api.StreamManager, que é responsável por solicitar e gerenciar streams de DAI. O construtor usa um elemento de vídeo, e a instância resultante usa um elemento da interface para processar as interações com o anúncio.

Em seguida, defina uma função para solicitar a transmissão ao vivo de veiculação de pod. Essa função primeiro cria um PodStreamRequest, o configura com os parâmetros streamRequest fornecidos na etapa 2 e, em seguida, chama streamManager.requestStream() com esse objeto de solicitação.

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

Veiculação de conjunto VOD

Para solicitar um conjunto de anúncios, crie um ima.dai.api.StreamManager, que é responsável por solicitar e gerenciar streams de DAI. O construtor usa um elemento de vídeo, e a instância resultante usa um elemento da interface para processar as interações com o anúncio.

Em seguida, defina uma função para solicitar o stream de VOD da veiculação de pod. Essa função primeiro cria um PodVodStreamRequest, o configura com os parâmetros streamRequest fornecidos na etapa 2 e, em seguida, chama streamManager.requestStream() com esse objeto de solicitação.

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

Processar eventos de stream

Disponibilização de pods de transmissão ao vivo

Em seguida, implemente listeners de eventos para os principais eventos de vídeo. Este exemplo processa os eventos STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED e AD_BREAK_ENDED chamando uma função onStreamEvent(). Essa função processa o carregamento e os erros do stream, além de desativar os controles do player enquanto um anúncio está em exibição, o que é exigido pelo SDK. Quando a transmissão é carregada, o player de vídeo carrega e reproduz o URL fornecido usando uma função 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);
}

Veiculação de conjunto de VOD

Em seguida, implemente listeners de eventos para os principais eventos de vídeo. Este exemplo processa os eventos STREAM_INITIALIZED, LOADED, ERROR, AD_BREAK_STARTED e AD_BREAK_ENDED chamando uma função onStreamEvent(). Essa função processa o carregamento e os erros do stream, além de desativar os controles do player durante a reprodução de um anúncio, o que é exigido pelo SDK.

Além disso, as transmissões de veiculação de conjunto de VOD exigem a chamada de StreamManager.loadStreamMetadata() em resposta ao evento STREAM_INITIALIZED. Você também precisa solicitar um URL da transmissão ao seu parceiro em tecnologia de vídeo (VTP). Quando a chamada loadStreamMetadata() é bem-sucedida, ela aciona um evento LOADED, em que você precisa chamar uma função loadStream() com o URL da transmissão para carregar e reproduzir o conteúdo.

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

Processar metadados de stream

Nesta etapa, você vai implementar listeners de eventos para metadados para notificar o SDK quando ocorrerem eventos de anúncio. A detecção de eventos de metadados in-stream pode variar de acordo com o formato do stream (HLS ou DASH), o tipo de stream (ao vivo ou VOD), o tipo de player e o tipo de back-end da DAI usado. Consulte nosso guia de metadados programados para mais informações.

Formato de stream HLS (streams ao vivo e VOD, player HLS.js)

Se você estiver usando um player HLS.js, detecte o evento FRAG_PARSING_METADATA do HLS.js para receber metadados ID3 e transmiti-los ao SDK com StreamManager.processMetadata().

Para reproduzir o vídeo automaticamente depois que tudo estiver carregado e pronto, detecte o evento MANIFEST_PARSED do HLS.js para acionar a reprodução.

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 (formato de transmissões DASH, tipo de transmissão ao vivo e VOD)

Se você estiver usando um player DASH.js, será necessário usar strings diferentes para detectar metadados ID3 em transmissões ao vivo ou de VOD:

  • Transmissões ao vivo: 'https://developer.apple.com/streaming/emsg-id3'
  • Streams de VOD: 'urn:google:dai:2018'

Transmita os metadados ID3 para o SDK com StreamManager.processMetadata().

Para mostrar automaticamente os controles de vídeo depois que tudo estiver carregado e pronto, detecte o evento MANIFEST_LOADED do 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 com transmissões ao vivo (formato de transmissões DASH)

Se você estiver usando o Shaka Player para reprodução de transmissões ao vivo, use a string 'emsg' para detectar eventos de metadados. Em seguida, use os dados da mensagem de evento na chamada para 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 com streams de VOD (formato de streams DASH)

Se você estiver usando o player Shaka para reprodução de stream de VOD, use a string 'timelineregionenter' para detectar eventos de metadados. Em seguida, use os dados da mensagem de evento na chamada para StreamManager.processMetadata() com a string '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);
       }
}

Processar eventos de player

Adicione listeners de eventos aos eventos pause e start do elemento de vídeo para permitir que o usuário retome a reprodução quando o SDK pausar durante os intervalos de anúncio.

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

Limpar recursos de DAI do IMA

Quando você terminar de solicitar e mostrar anúncios de display em um stream de veiculação de pod com o SDK da DAI do IMA, sugerimos que limpe todos os recursos após o término da sessão de veiculação de pod. Chame StreamManager.destroy() para interromper a reprodução do stream, interromper todo o rastreamento de anúncios e liberar todos os recursos de stream carregados.

Para saber mais sobre os recursos avançados do SDK, consulte os outros guias ou os exemplos no GitHub.