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 oPodStreamRequesttambé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.
Usando uma linha de comando, no diretório que contém o arquivo
index.html, execute:python -m http.server 8000Em 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.