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 do DAI do IMA para HTML5 com um player de vídeo que depende de 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 pod 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 em HTML5 no GitHub.

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

A implementação da veiculação de conjunto usando o SDK da 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 do IMA para DAI, 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 manipulador de manifesto ou parceiro terceirizado usando a veiculação de conjunto. Ele precisa exigir que você insira o ID do stream fornecido pelo SDK do 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 manipulador de manifesto ou pelo 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 do 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 do anúncio 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 pods. Essa função primeiro cria um PodStreamRequest, configura-o 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 de 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 do anúncio para processar as interações com o anúncio.

Em seguida, defina uma função para solicitar o stream de VOD de veiculação de pod. Essa função primeiro cria um PodVodStreamRequest, configura-o 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 o stream é carregado, 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 pod 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 streams DASH, tipo de stream ao vivo e VOD)

Se você estiver usando um player DASH.js, será necessário usar strings diferentes para detectar metadados ID3 em streams 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 player Shaka 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 em um stream de veiculação de conjunto com o SDK do IMA DAI, sugerimos que limpe todos os recursos após a conclusão da sessão de veiculação de conjunto. 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.