IMA DAI SDK スタートガイド

IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK は、 VAST 準拠の任意の広告サーバーから広告をリクエストし、アプリ内の広告再生を管理できます。IMA DAI SDK を使用すると、アプリは広告とコンテンツ動画(VOD またはライブ コンテンツ)のストリーム リクエストを行います。SDK は統合された動画ストリームを返すため、アプリ内で広告動画とコンテンツ動画の切り替えを管理する必要はありません。

関心のある DAI ソリューションを選択する

Pod Serving DAI

このガイドでは、hls.js に依存する動画プレーヤーで IMA DAI SDK for HTML5 を使用して、ライブ コンテンツまたは VOD コンテンツの DAI Pod Serving ストリームを再生する方法について説明します。HLS.js と Safari の再生の両方をサポートする、統合が完了したサンプルを表示または確認するには、HLS Pod サービングのサンプルをご覧ください。DASH.js のサポートについては、DASH Pod サービング例をご覧ください。これらのサンプルアプリは、HTML5 DAI GitHub リリース ページからダウンロードできます。

DAI Pod Serving の概要

IMA DAI SDK を使用して Pod サービングを実装するには、次の 2 つの主要コンポーネントが必要です。このガイドでは、それらについて説明します。

  • 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 Server などの他のホスト型開発環境またはウェブサーバーを使用することもできます。

動画プレーヤーを作成する

まず、dai.html を変更して、広告 UI 要素に使用する HTML5 動画要素と div を作成します。また、dai.css ファイルと dai.js ファイルを読み込み、hls.js 動画プレーヤーをインポートするために必要なタグを追加します。

次に、dai.css を変更して、ページ要素のサイズと位置を指定します。最後に、dai.js で、ストリーム リクエスト情報を保持する変数と、ページの読み込み時に実行する initPlayer() 関数を定義します。

ストリーム リクエスト定数は次のとおりです。

  • BACKUP_STREAM: 広告処理で致命的なエラーが発生した場合に再生するバックアップ ストリームの URL。

  • STREAM_URL: ライブ配信でのみ使用されます。マニフェスト マニピュレータまたは連続広告配信を使用する第三者のパートナーから提供される動画ストリーム URL。リクエストを行う前に、IMA DAI SDK から提供されたストリーム ID を挿入する必要があります。この場合、ストリーム URL にはプレースホルダ [[STREAMID]] が含まれます。これは、リクエストを送信する前にストリーム ID に置き換えられます。

  • NETWORK_CODE: アド マネージャー 360 アカウントのネットワーク コード。

  • CUSTOM_ASSET_KEY: ライブ配信でのみ使用されます。アド マネージャー 360 のポッド配信イベントを識別するカスタム アセットキー。これは、マニフェスト マニピュレータまたはサードパーティの Pod Serving パートナーによって作成できます。

  • 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.html で、dai.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 ストリームのリクエストを行う

ライブ配信 Pod の配信

広告セットをリクエストするには、DAI ストリームのリクエストと管理を行う ima.dai.api.StreamManager を作成します。コンストラクタは動画要素を受け取り、生成されたインスタンスは広告 UI 要素を受け取って広告インタラクションを処理します。

次に、Pod Serving ライブ配信をリクエストする関数を定義します。この関数は、まず 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 Pod Serving

広告セットをリクエストするには、DAI ストリームのリクエストと管理を行う ima.dai.api.StreamManager を作成します。コンストラクタは動画要素を受け取り、生成されたインスタンスは広告 UI 要素を受け取って広告インタラクションを処理します。

次に、Pod Serving 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);
}

ストリーム イベントを処理する

ライブ配信 Pod の配信

次に、動画の主要なイベントのイベント リスナーを実装します。この例では、onStreamEvent() 関数を呼び出して、STREAM_INITIALIZEDERRORAD_BREAK_STARTEDAD_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 Pod Serving

次に、動画の主要なイベントのイベント リスナーを実装します。この例では、onStreamEvent() 関数を呼び出して、STREAM_INITIALIZEDLOADEDERRORAD_BREAK_STARTEDAD_BREAK_ENDED イベントを処理します。この関数は、ストリームの読み込みとエラーを処理します。また、広告の再生中にプレーヤーのコントロールを無効にします。これは SDK で必須です。

また、VOD Pod サービング ストリームでは、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 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});
}

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

プレーヤー イベントを処理する

動画要素の 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 を使用して Pod Serving ストリームで広告のリクエストと表示を正常に完了したら、Pod Serving セッションの完了後にリソースをクリーンアップすることをおすすめします。StreamManager.destroy() を呼び出して、ストリームの再生を停止し、すべての広告トラッキングを停止し、読み込まれたすべてのストリーム アセットを解放します。

SDK の高度な機能については、他のガイドまたは GitHub のサンプルをご覧ください。