IMA DAI SDK 시작하기

IMA SDK를 사용하면 웹사이트와 앱에 멀티미디어 광고를 쉽게 통합할 수 있습니다. IMA SDK는 모든 VAST 호환 광고 서버에서 광고를 요청하고 앱에서 광고 재생을 관리할 수 있습니다. IMA DAI SDK를 사용하면 앱에서 광고 및 콘텐츠 동영상(VOD 또는 라이브 콘텐츠)에 대한 스트림을 요청합니다. 그러면 SDK가 결합된 동영상 스트림을 반환하므로 앱 내에서 광고 동영상과 콘텐츠 동영상 간에 전환을 관리할 필요가 없습니다.

관심 있는 DAI 솔루션을 선택합니다

DAI 광고 모음 게재

이 가이드에서는 재생에 hls.js를 사용하는 동영상 플레이어와 함께 HTML5용 IMA DAI SDK를 사용하여 라이브 또는 VOD 콘텐츠의 DAI 광고 모음 게재 스트림을 재생하는 방법을 설명합니다. HLS.js와 Safari 재생을 모두 지원하는 완성된 샘플 통합을 보거나 따라 하려면 HLS Pod 게재 예시를 참고하세요. DASH.js 지원은 DASH 포드 게재 예시를 참고하세요. 이러한 샘플 앱은 HTML5 DAI GitHub 출시 페이지에서 다운로드할 수 있습니다.

DAI 광고 모음 게재 개요

IMA DAI SDK를 사용하여 광고 모음 게재를 구현하려면 이 가이드에 설명된 두 가지 주요 구성요소가 필요합니다.

  • PodStreamRequest/PodVodStreamRequest: Google 광고 서버에 대한 스트림 요청을 정의하는 객체입니다. 요청은 네트워크 코드를 지정하며 PodStreamRequest에는 커스텀 애셋 키와 선택적 API 키도 필요합니다. 둘 다 다른 선택적 매개변수를 포함합니다.

  • StreamManager: 동영상 스트림과 IMA DAI SDK 간의 통신(예: 추적 핑 실행 및 스트림 이벤트를 게시자에게 전달)을 처리하는 객체입니다.

기본 요건

시작하기 전에 다음이 필요합니다.

  • 빈 파일 3개:

    • dai.html
    • dai.css
    • dai.js
  • 컴퓨터에 설치된 Python 또는 테스트에 사용할 웹 서버 또는 기타 호스팅된 개발 환경

개발 환경 구성

SDK는 로드되는 페이지와 동일한 프로토콜을 사용하여 종속 항목을 로드하므로 웹 서버를 사용하여 앱을 테스트해야 합니다. 로컬 개발 서버를 시작하는 빠른 방법은 Python의 내장 서버를 사용하는 것입니다.

  1. index.html 파일이 있는 디렉터리에서 명령줄을 사용하여 다음을 실행합니다.

    python -m http.server 8000
    
  2. 웹브라우저에서 http://localhost:8000/로 이동합니다.

    Apache HTTP 서버와 같은 기타 호스팅된 개발 환경이나 웹 서버도 사용할 수 있습니다.

동영상 플레이어 만들기

먼저 dai.html을 수정하여 HTML5 동영상 요소와 광고 UI 요소에 사용할 div를 만듭니다. 또한 dai.cssdai.js 파일을 로드하고 hls.js 동영상 플레이어를 가져오는 데 필요한 태그를 추가합니다.

그런 다음 dai.css를 수정하여 페이지 요소의 크기와 위치를 지정합니다. 마지막으로 dai.js에서 스트림 요청 정보를 보관할 변수와 페이지가 로드될 때 실행할 initPlayer() 함수를 정의합니다.

스트림 요청 상수는 다음과 같습니다.

  • BACKUP_STREAM: 광고 프로세스에 심각한 오류가 발생할 경우 재생할 백업 스트림의 URL입니다.

  • STREAM_URL: 라이브 스트림에만 사용됩니다. 광고 모음 게재를 사용하는 매니페스트 조작기 또는 서드 파티 파트너가 제공한 동영상 스트림 URL입니다. 요청하기 전에 IMA DAI SDK에서 제공한 스트림 ID를 삽입해야 합니다. 이 경우 스트림 URL에 자리표시자 [[STREAMID]]가 포함되며, 이 자리표시자는 요청하기 전에 스트림 ID로 대체됩니다.

  • NETWORK_CODE: Ad Manager 360 계정의 네트워크 코드입니다.

  • CUSTOM_ASSET_KEY: 라이브 스트림에만 사용됩니다. Ad Manager 360에서 광고 모음 게재 이벤트를 식별하는 맞춤 애셋 키입니다. 매니페스트 조작기 또는 서드 파티 광고 모음 게재 파트너가 이를 만들 수 있습니다.

  • API_KEY: 라이브 스트림에만 사용됩니다. IMA DAI SDK에서 스트림 ID를 검색하는 데 필요할 수 있는 선택적 API 키입니다.

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="ad-ui"></div>
</body>
</html>

dai.css

#video,
#ad-ui {
  width: 640px;
  height: 360px;
  position: absolute;
  top: 35px;
  left: 0;
}

#ad-ui {
  cursor: pointer;
}

dai.js

var BACKUP_STREAM =
    'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'

// Stream Config.
const STREAM_URL = "https://encodersim.sandbox.google.com/masterPlaylist/...&stream_id=[[STREAMID]]";
const NETWORK_CODE = "51636543";
const CUSTOM_ASSET_KEY = "google-sample";
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.htmldai.js 태그 앞에 스크립트 태그를 사용하여 DAI 프레임워크를 추가합니다.

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 초기화 및 라이브 또는 VOD 스트림 요청

라이브 스트림 포드 게재

광고 세트를 요청하려면 DAI 스트림을 요청하고 관리하는 ima.dai.api.StreamManager를 만듭니다. 생성자는 동영상 요소를 사용하고 생성된 인스턴스는 광고 UI 요소를 사용하여 광고 상호작용을 처리합니다.

그런 다음 포드 게재 라이브 스트림을 요청하는 함수를 정의합니다. 이 함수는 먼저 PodStreamRequest를 만들고 2단계에서 제공된 streamRequest 매개변수로 구성한 다음 해당 요청 객체로 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);
}

VOD 광고 모음 게재

광고 세트를 요청하려면 DAI 스트림을 요청하고 관리하는 ima.dai.api.StreamManager를 만듭니다. 생성자는 동영상 요소를 사용하고 결과 인스턴스는 광고 UI 요소를 사용하여 광고 상호작용을 처리합니다.

그런 다음 포드 게재 VOD 스트림을 요청하는 함수를 정의합니다. 이 함수는 먼저 PodVodStreamRequest를 만들고 2단계에서 제공된 streamRequest 매개변수로 구성한 다음 해당 요청 객체로 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);
}

스트림 이벤트 처리

라이브 스트림 포드 게재

다음으로 주요 동영상 이벤트에 대한 이벤트 리스너를 구현합니다. 이 예에서는 onStreamEvent() 함수를 호출하여 STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED, AD_BREAK_ENDED 이벤트를 처리합니다. 이 함수는 스트림 로드 및 오류를 처리하고 광고가 재생되는 동안 플레이어 컨트롤을 사용 중지합니다. 이는 SDK에 필요합니다. 스트림이 로드되면 동영상 플레이어는 loadStream() 함수를 사용하여 제공된 URL을 로드하고 재생합니다.

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

VOD 광고 모음 게재

다음으로 주요 동영상 이벤트에 대한 이벤트 리스너를 구현합니다. 이 예에서는 onStreamEvent() 함수를 호출하여 STREAM_INITIALIZED, LOADED, ERROR, AD_BREAK_STARTED, AD_BREAK_ENDED 이벤트를 처리합니다. 이 함수는 스트림 로드 및 오류를 처리하고 광고가 재생되는 동안 플레이어 컨트롤을 사용 중지합니다. 이는 SDK에 필요합니다.

또한 VOD 포드 게재 스트림은 STREAM_INITIALIZED 이벤트에 대한 응답으로 StreamManager.loadStreamMetadata()를 호출해야 합니다. 동영상 기술 파트너 (VTP)에게 스트림 URL도 요청해야 합니다. loadStreamMetadata() 호출이 성공하면 LOADED 이벤트가 트리거되며 여기서 스트림 URL을 사용하여 loadStream() 함수를 호출하여 스트림을 로드하고 재생해야 합니다.

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), 스트림 유형 (라이브 또는 VOD 스트림), 플레이어 유형, 사용 중인 DAI 백엔드 유형에 따라 다를 수 있습니다. 자세한 내용은 타임스탬프 메타데이터 가이드를 참고하세요.

HLS 스트림 형식 (라이브 및 VOD 스트림, HLS.js 플레이어)

HLS.js 플레이어를 사용하는 경우 HLS.js FRAG_PARSING_METADATA 이벤트를 리슨하여 ID3 메타데이터를 가져와 StreamManager.processMetadata()를 사용하여 SDK에 전달합니다.

모든 항목이 로드되고 준비되면 동영상을 자동으로 재생하려면 HLS.js MANIFEST_PARSED 이벤트를 수신 대기하여 재생을 트리거합니다.

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 플레이어를 사용하는 경우 라이브 또는 VOD 스트림의 ID3 메타데이터를 리슨하려면 다른 문자열을 사용해야 합니다.

  • 라이브 스트림: 'https://developer.apple.com/streaming/emsg-id3'
  • VOD 스트림: 'urn:google:dai:2018'

StreamManager.processMetadata()를 사용하여 ID3 메타데이터를 SDK에 전달합니다.

모든 항목이 로드되고 준비되면 동영상 컨트롤을 자동으로 표시하려면 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});
}

VOD 스트림이 포함된 Shaka Player (DASH 스트림 형식)

VOD 스트림 재생에 Shaka 플레이어를 사용하는 경우 'timelineregionenter' 문자열을 사용하여 메타데이터 이벤트를 수신 대기합니다. 그런 다음 'urn:google:dai:2018' 문자열과 함께 StreamManager.processMetadata() 호출에서 이벤트 메시지 데이터를 사용합니다.

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

플레이어 이벤트 처리

동영상 요소의 pausestart 이벤트에 이벤트 리스너를 추가하여 광고 시점 중에 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의 샘플을 참고하세요.