创建广告管理器类

ads_manager.js 中,为 IMA SDK StreamManager 定义一个封装容器类,用于发出串流请求、获取广告连播清单、监听 IMA 串流事件,并将 emsg 事件传递给 IMA SDK。

ads_manager.js 中,IMA HbbTV 示例应用会设置以下方法:

  • requestStream()
  • onStreamEvent()
  • onEmsgEvent()
  • loadAdPodManifest()

初始化广告管理器

初始化广告管理器类,并为 IMA 串流事件设置监听器。在此调用中,使用 VideoPlayer.setEmsgEventHandler() 方法设置 emsg 事件处理脚本。

/**
 * Wraps IMA SDK ad stream manager.
 * @param {!VideoPlayer} videoPlayer Reference an instance of the wrapper from
 * video_player.js.
 */
var AdManager = function(videoPlayer) {
  this.streamData = null;
  this.videoPlayer = videoPlayer;
  // Ad UI is not supported for HBBTV, so no 'adUiElement' is passed in the
  // StreamManager constructor.
  this.streamManager = new google.ima.dai.api.StreamManager(
      this.videoPlayer.videoElement);
  this.streamManager.addEventListener(
      [
        google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
        google.ima.dai.api.StreamEvent.Type.ERROR,
        google.ima.dai.api.StreamEvent.Type.CLICK,
        google.ima.dai.api.StreamEvent.Type.STARTED,
        google.ima.dai.api.StreamEvent.Type.FIRST_QUARTILE,
        google.ima.dai.api.StreamEvent.Type.MIDPOINT,
        google.ima.dai.api.StreamEvent.Type.THIRD_QUARTILE,
        google.ima.dai.api.StreamEvent.Type.COMPLETE,
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED,
        google.ima.dai.api.StreamEvent.Type.AD_PROGRESS,
        google.ima.dai.api.StreamEvent.Type.PAUSED,
        google.ima.dai.api.StreamEvent.Type.RESUMED
      ],
      this.onStreamEvent.bind(this),
      false);

  this.videoPlayer.setEmsgEventHandler(this.onEmsgEvent, this);
};

请求广告连播流

创建 AdManager.requestStream() 方法,以使用 Google Ad Manager 广告联盟代码和直播的自定义素材资源键创建 PodStreamRequest 对象。使用以下串流参数的 IMA 示例 DASH 文件夹广告投放串流测试您的 HbbTV 应用:

  • 影音平台代码'21775744923'
  • 自定义素材资源键'hbbtv-dash'
/**
 * Makes a pod stream request.
 * @param {string} networkCode The network code.
 * @param {string} customAssetKey The custom asset key.
 */
AdManager.prototype.requestStream = function(networkCode, customAssetKey) {
  var streamRequest = new google.ima.dai.api.PodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.customAssetKey = customAssetKey;
  streamRequest.format = 'dash';
  debugView.log('AdsManager: make PodStreamRequest');
  this.streamManager.requestStream(streamRequest);
};

监听广告串流事件

创建 AdManager.onStreamEvent() 方法来处理应用对 IMA 串流事件 STREAM_INITIALIZEDAD_BREAK_STARTEDAD_BREAK_ENDED 的响应。

/**
 * Handles IMA playback events.
 * @param {!Event} event The event object.
 */
AdManager.prototype.onStreamEvent = function(event) {
  switch (event.type) {
    // Once the stream response data is received, generate pod manifest url
    // for the video stream.
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      debugView.log('IMA SDK: stream initialized');
      this.streamData = event.getStreamData();
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      break;
    // Hide video controls while ad is playing.
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      debugView.log('IMA SDK: ad break started');
      this.adPlaying = true;
      this.adBreakStarted = true;
      break;
    // Show video controls when ad ends.
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      debugView.log('IMA SDK: ad break ended');
      this.adPlaying = false;
      this.adBreakStarted = false;
      break;
    // Update ad countdown timers.
    case google.ima.dai.api.StreamEvent.Type.AD_PROGRESS:
      break;
    default:
      debugView.log('IMA SDK: ' + event.type);
      break;
  }
};

处理广告串流元数据

如需将 emsg 事件信息传递给 IMA,请使用 StreamManager.processMetadata() 方法创建 AdManager.onEmsgEvent() 方法。视频播放器类使用 VideoPlayer.setEmsgEventHandler() 方法调用此方法。

/**
 * Callback on Emsg event.
 * Instructs IMA SDK to fire back VAST events accordingly.
 * @param {!Event} event The event object.
 */
AdManager.prototype.onEmsgEvent = function(event) {
  var data = event.event.messageData;
  var pts = event.event.calculatedPresentationTime;
  if ((data instanceof Uint8Array) && data.byteLength > 0) {
    this.streamManager.processMetadata('ID3', data, pts);
  }
};

加载广告连播清单

创建 AdManager.loadAdPodManifest() 方法,以便使用视频播放器预加载广告连播清单。使用方法:DASH pod 清单中的结构构建清单网址。

/**
 * Creates DAI pod url and instructs video player to load manifest.
 * @param {string} networkCode The network code.
 * @param {string} customAssetKey The custom asset key.
 * @param {number} podDuration The duration of the ad pod.
 */
AdManager.prototype.loadAdPodManifest =
    function(networkCode, customAssetKey, podDuration) {
  if (!this.streamData) {
    debugView.log('IMA SDK: No DAI pod session registered.');
    return;
  }

  var MANIFEST_BASE_URL = 'https://dai.google.com/linear/pods/v1/dash/network/';
  // Method: DASH pod manifest reference docs:
  // https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_dash_pod_manifest
  var manifestUrl = MANIFEST_BASE_URL + networkCode + '/custom_asset/' +
    customAssetKey + '/stream/' + this.streamData.streamId + '/pod/' +
    this.getPodId() + '/manifest.mpd?pd=' + podDuration;
  this.videoPlayer.preload(manifestUrl);
};

HbbTV 示例应用使用随机生成的唯一 podId。在正式版应用中,podId 是一个从 1 开始的整数,并且在每次广告插播时递增 1。确保广告插播的所有观看者都具有相同的 podId 值。如需获取 podId,我们建议您使用广告插播提前通知 (EABN) API。在生产环境中,在 HbbTV 流事件 AD_BREAK_ANNOUNCE 中添加 podIdpodDuration

接下来,为与 HbbTV 广播进行交互的 HbbTV 应用创建主要应用类。