设置 IMA SDK for DAI

借助 IMA SDK,您可以轻松将多媒体广告集成到您的网站和应用中。IMA SDK 可以从任何 与 VAST 兼容的广告服务器请求广告,并管理应用中的广告播放。借助 IMA DAI SDK,应用可以针对广告和内容视频(VOD 或直播内容)发出流式传输请求。然后,SDK 会返回一个合并的视频串流,这样您就不必在应用中管理广告视频和内容视频之间的切换。

选择您感兴趣的 DAI 解决方案

全方位 DAI

本指南介绍了如何将 IMA DAI SDK 集成到视频播放器应用中。如果您想查看或跟随已完成的示例集成,请从 GitHub 下载简单示例

IMA DAI 概览

实现 IMA DAI SDK 涉及两个主要组件,如本指南中所示:

  • StreamRequest - VODStreamRequest LiveStreamRequest:用于定义数据流请求的对象。流式传输请求可以是视频点播或直播。直播请求指定素材资源键,而 VOD 请求指定 CMS ID 和视频 ID。这两种请求类型都可以选择包含访问指定串流所需的 API 密钥,以及一个 Google Ad Manager 广告资源网代码,以便 IMA SDK 处理 Google Ad Manager 设置中指定的广告标识符。
  • StreamManager:用于处理动态广告插播数据流和与 DAI 后端的互动的对象。直播管理器还会处理跟踪 ping,并将直播和广告事件转发给发布商。

前提条件

  • 三个空文件
    • dai.html
    • dai.css
    • dai.js
  • 在用于测试的计算机或网络服务器上安装 Python

启动开发服务器

由于 IMA DAI SDK 加载依赖项所用的协议与其加载时所在网页使用的协议相同,因此您需要使用网络服务器来测试应用。要启动本地开发服务器,最快捷的方法是使用 Python 的内置服务器。

  1. 在包含 index.html 文件的目录下使用命令行运行以下命令:

    python -m http.server 8000
  2. 在网络浏览器中,前往 http://localhost:8000/

    您也可以使用任何其他网络服务器,例如 Apache HTTP Server

创建视频播放器

首先,修改 dai.html,以创建一个 HTML5 视频元素和一个用于点击的 div。以下示例会导入 IMA DAI SDK。如需了解详情,请参阅导入 IMA DAI SDK

此外,还要添加必要的标记来加载 dai.cssdai.js 文件,以及导入 hls.js 视频播放器。然后,修改 dai.css 以指定页面元素的大小和位置。最后,在 dai.js 中,定义用于存储串流请求信息的变量、在页面加载时运行的 initPlayer() 函数,并设置播放按钮以在点击时请求串流。

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css">
</head>
<body onLoad="initPlayer()">
  <h2>IMA SDK DAI Demo (HLS.JS)</h2>
  <video id="video"></video>
  <div id="adUi"></div>
  <button id="play-button">Play</button>
</body>
</html>

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

#adUi {
  cursor: pointer;
}

#play-button {
  position: absolute;
  top: 400px;
  left: 15px;
}
// This stream will be played if ad-enabled playback fails.
const BACKUP_STREAM =
    'http://storage.googleapis.com/testtopbox-public/video_content/bbb/' +
    'master.m3u8';

// Live stream asset key.
// const TEST_ASSET_KEY = 'c-rArva4ShKVIAkNfy6HUQ';

// VOD content source and video IDs.
const TEST_CONTENT_SOURCE_ID = '2548831';
const TEST_VIDEO_ID = 'tears-of-steel';

// Ad Manager network code.
const NETWORK_CODE = '21775744923';
const API_KEY = null;

// StreamManager which will be used to request ad-enabled streams.
let streamManager;

// hls.js video player
const hls = new Hls();

// Video element
let videoElement;

// Ad UI element
let adUiElement;

// The play/resume button
let playButton;

// Whether the stream is currently in an ad break.
let adBreak = false;

/**
 * Initializes the video player.
 */
function initPlayer() {
  videoElement = document.getElementById('video');
  playButton = document.getElementById('play-button');
  adUiElement = document.getElementById('adUi');
  createStreamManager();
  listenForMetadata();

  // Show the video controls when the video is paused during an ad break,
  // and hide them when ad playback resumes.
  videoElement.addEventListener('pause', () => {
    if (adBreak) {
      showVideoControls();
    }
  });
  videoElement.addEventListener('play', () => {
    if (adBreak) {
      hideVideoControls();
    }
  });

  playButton.addEventListener('click', () => {
    console.log('initiatePlayback');
    requestStream();
    // Hide this play button after the first click to request the stream.
    playButton.style.display = 'none';
  });
}

如需在暂停的广告插播期间继续播放,请为视频元素的 pausestart 事件设置事件监听器,以显示和隐藏播放器控件。

/**
 * Hides the video controls.
 */
function hideVideoControls() {
  videoElement.controls = false;
  adUiElement.style.display = 'block';
}

/**
 * Shows the video controls.
 */
function showVideoControls() {
  videoElement.controls = true;
  adUiElement.style.display = 'none';
}

加载 IMA DAI SDK

接下来,在 dai.html 中使用脚本标记添加 IMA 框架,将其放在 dai.js 对应的标记之前。

<script src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>

初始化 StreamManager

如需请求一组广告,请创建一个 ima.dai.api.StreamManager,该实例负责请求和管理 DAI 数据流。该构造函数接受视频元素和广告界面元素来处理广告点击。

/**
 * Create the StreamManager and listen to stream events.
 */
function createStreamManager() {
  streamManager =
      new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  streamManager.addEventListener(
      google.ima.dai.api.StreamEvent.Type.LOADED, onStreamEvent);
  streamManager.addEventListener(
      google.ima.dai.api.StreamEvent.Type.ERROR, onStreamEvent);
  streamManager.addEventListener(
      google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED, onStreamEvent);
  streamManager.addEventListener(
      google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED, onStreamEvent);
}

发出流式请求

定义用于请求数据流的函数。此示例包含适用于 VOD 和直播的函数,这些函数会创建 VODStreamRequest 类和 LiveStreamRequest 类的实例。创建 streamRequest 实例后,使用串流请求实例调用 streamManager.requestStream() 方法。

/**
 * Makes a stream request and plays the stream.
 */
function requestStream() {
  requestVODStream(TEST_CONTENT_SOURCE_ID, TEST_VIDEO_ID, NETWORK_CODE, API_KEY);
  // Uncomment line below and comment one above to request a LIVE stream.
  // requestLiveStream(TEST_ASSET_KEY, NETWORK_CODE, API_KEY);
}

/**
 * Requests a Live stream with ads.
 * @param {string} assetKey
 * @param {?string} networkCode
 * @param {?string} apiKey
 */
function requestLiveStream(assetKey, networkCode, apiKey) {
  const streamRequest = new google.ima.dai.api.LiveStreamRequest();
  streamRequest.assetKey = assetKey;
  streamRequest.networkCode = networkCode;
  streamRequest.apiKey = apiKey;
  streamManager.requestStream(streamRequest);
}

/**
 * Requests a VOD stream with ads.
 * @param {string} cmsId
 * @param {string} videoId
 * @param {?string} networkCode
 * @param {?string} apiKey
 */
function requestVODStream(cmsId, videoId, networkCode, apiKey) {
  const streamRequest = new google.ima.dai.api.VODStreamRequest();
  streamRequest.contentSourceId = cmsId;
  streamRequest.videoId = videoId;
  streamRequest.networkCode = networkCode;
  streamRequest.apiKey = apiKey;
  streamManager.requestStream(streamRequest);
}

这两种串流请求方法都接受可选的 API 密钥。如果您使用的是受保护的串流,则需要创建 DAI 身份验证密钥。如需了解详情,请参阅对 DAI 视频流请求进行身份验证。此示例中的两个串流都未使用 DAI 身份验证密钥进行保护,因此不会使用 apiKey

解析直播元数据(仅限直播)

对于直播,您还需要添加一个处理脚本来监听定时元数据事件,并将事件转发到 StreamManager 类,以便 IMA 在广告插播期间发出广告事件:

/**
 * Set up metadata listeners to pass metadata to the StreamManager.
 */
function listenForMetadata() {
  // Only used in LIVE streams. Timed metadata is handled differently
  // by different video players, and the IMA SDK provides two ways
  // to pass in metadata, StreamManager.processMetadata() and
  // StreamManager.onTimedMetadata().
  //
  // Use StreamManager.onTimedMetadata() if your video player parses
  // the metadata itself.
  // Use StreamManager.processMetadata() if your video player provides raw
  // ID3 tags, as with hls.js.
  hls.on(Hls.Events.FRAG_PARSING_METADATA, function(event, data) {
    if (streamManager && data) {
      // For each ID3 tag in our metadata, we pass in the type - ID3, the
      // tag data (a byte array), and the presentation timestamp (PTS).
      data.samples.forEach(function(sample) {
        streamManager.processMetadata('ID3', sample.data, sample.pts);
      });
    }
  });
}

本指南使用 hls.js 播放器进行流式播放,但您的元数据实现取决于您使用的播放器类型。

处理数据流事件

为主要视频事件实现事件监听器。此示例通过调用 onStreamEvent() 函数来处理 LOADEDERRORAD_BREAK_STARTEDAD_BREAK_ENDED 事件。此函数会处理串流加载、串流错误,以及在广告播放期间停用播放器控件(这是 IMA SDK 的要求)。

/**
 * Responds to a stream event.
 * @param {!google.ima.dai.api.StreamEvent} e
 */
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.LOADED:
      console.log('Stream loaded');
      loadUrl(e.getStreamData().url);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadUrl(BACKUP_STREAM);
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      adBreak = true;
      hideVideoControls();
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      adBreak = false;
      showVideoControls();
      break;
    default:
      break;
  }
}

/**
 * Loads and plays a Url.
 * @param {string} url
 */
function loadUrl(url) {
  console.log('Loading:' + url);
  hls.loadSource(url);
  hls.attachMedia(videoElement);
  hls.on(Hls.Events.MANIFEST_PARSED, function() {
    console.log('Video Play');
    videoElement.play();
  });
}

加载数据流后,视频播放器会使用 loadUrl() 函数加载并播放所提供的网址。

大功告成!现在,您可以使用 IMA DAI SDK 请求和展示广告了。如需了解更高级的 SDK 功能,请参阅其他指南或 GitHub 上的示例