自动制作广告播放列表

IMA HTML5 SDK 支持完全自动化的广告播放列表。此功能会在投放广告时,按照 Google Ad Manager 中指定的方式将广告插播点插入内容中。此外,它还大大简化了支持广告插播(包括前贴片广告、中贴片广告和后贴片广告)所需的视频播放器代码。

  • 创建 AdsManager 时,系统会使用 getAdsManager 调用传入 contentPlayback 对象。此对象必须具有一个 currentTime 属性,用于返回视频的当前播放头位置。如果您使用 HTML5 video 元素来展示内容,只需将该元素传递给 SDK 即可。此对象用于跟踪内容播放进度,以便在 Ad Manager 中指定的时间自动插入广告插播时间点。您还需要告知 SDK,您希望它代表您处理内容状态。
    var adsRenderingSettings = new google.ima.AdsRenderingSettings();
    adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
    adsManager = adsManagerLoadedEvent.getAdsManager(
        videoContent, adsRenderingSettings); // See API reference for contentPlayback.
  • 为确保播放后贴片广告,您需要在内容播放完毕时告知 SDK。这有点棘手,因为在某些情况下,SDK 会使用您的视频播放器播放广告,因此您需要确保仅告知 SDK 内容播放完毕的时间,而不是广告播放完毕的时间。您可以使用以下代码执行此操作:
    var videoContent = document.getElementById('contentElement');
    var contentEndedListener = function() {adsLoader.contentComplete();};
    
    videoContent.addEventListener('ended', contentEndedListener);
    
    function onContentPauseRequested() {
      contentElement.removeEventListener('ended', contentEndedListener);
      ...
    }
    
    function onContentResumeRequested() {
      contentElement.addEventListener('ended', contentEndedListener);
      ...
    }
  • CONTENT_PAUSE_REQUESTEDCONTENT_RESUME_REQUESTED 事件用于在播放广告插播时暂停和继续播放内容。
  • 如果您的视频播放器支持拖动跳转,并且在用户拖动时视频播放器的当前时间属性会更新,则 SDK 无法区分内容正常播放和用户跳转内容。 您必须使用自定义 contentPlayback 对象作为 getAdsManager 的参数。 如需查看此用例的示例,请参阅跳转问题

注意:当内容播放完毕或用户停止播放时,请务必调用 AdsLoader.contentComplete,以向 SDK 发出内容播放完毕的信号。然后,SDK 会播放片尾广告插播(如果已安排)。播放完所有广告插播时,系统会引发 ALL_ADS_COMPLETED 事件。此外,请注意,内容跟踪会在调用 init() 时开始,并且您应始终在播放内容之前调用 init()

停用自动播放广告插播

在某些情况下,您可能希望在准备就绪之前阻止 SDK 播放广告插播。在这种情况下,您可以停用广告插播的自动播放,改为在您准备好播放广告插播时通知 SDK。采用此配置后,SDK 加载广告插播时,会触发 AD_BREAK_READY 事件。当播放器准备好开始广告插播时,您可以调用 adsManager.start():

function requestAds() {}
  ...
  adsLoader.getSettings().setAutoPlayAdBreaks(false);
  ...
}

function onAdsManagerLoaded() {
  ...
  // For non-auto ad breaks, listen for ad break ready
  adsManager.addEventListener(
      google.ima.AdEvent.Type.AD_BREAK_READY,
      adBreakReadyHandler);
  ...
}

function adBreakReadyHandler() {
  // Once we're ready to play ads. To skip this ad break, simply return
  // from this handler without calling adsManager.start().
  adsManager.start();
}

试试看

如需查看有效的实现,请参阅以下代码。

跳转时遇到问题

如果您使用广告规则,则可能会遇到点击并拖动跳转时出现问题的情况。 具体而言,用户点击并拖动以跳过视频中的多个中贴片广告连播后,可能会看到其中 2 个或更多连播在内容恢复播放之前播放。这是因为视频播放头时间会在用户跳转时更新;如果 SDK 在用户跳过广告时恰好轮询当前时间,则可能会认为应播放广告。当内容继续播放时,系统会先播放该广告,然后播放从快进到该广告以来的最新广告。如需直观地了解此问题,请参阅下图:

保存用户开始快进时的当前时间,并在 SDK 请求时报告该时间,直到用户恢复正常播放。如需直观了解此解决方案,请参阅下图:

通过此解决方案,您可以正确跳过 0:10 的中贴片广告,仅播放 0:20 的中贴片广告。这可在以下代码段中使用自定义播放头跟踪器完成。此代码包含下载页面上提供的高级 HTML5 示例中对 ads.js 所做的修改(以粗体显示)。

var Ads = function(application, videoPlayer) {
  ...
  this.currentTime = 0;
  setInterval(this.updateCurrentTime, 1000);
};

Ads.prototype.updateCurrentTime = function() {
  if (!this.videoPlayer_.contentPlayer.seeking) {
    this.currentTime = this.videoPlayer_.contentPlayer.currentTime;
  }
};

Ads.prototype.onAdsManagerLoaded_ = function(adsManagerLoadedEvent) {
  this.application_.log('Ads loaded.');
  this.adsManager_ = adsManagerLoadedEvent.getAdsManager(this);
  this.processAdsManager_(this.adsManager_);
};

移动 Safari 的已知问题

此方法应该适用于所有平台(移动 Safari 除外)。在移动 Safari 上,视频标记的 seeking 属性未正确实现(始终返回 false)。为此,您需要自行检查用户是否正在快进视频。以下是此方法的示例代码。再次说明一下,加粗的代码行是对现有代码的修改。

var Ads = function(application, videoPlayer) {
  ...
  this.currentTime = 0;
  setInterval(this.updateCurrentTime, 1000);
  this.seeking = false;
  this.seekCheckInterval = 1000;
  // You may need to adjust this value, depending on your platform
  this.seekThreshold = 100;
  this.previousTime = 0;
  setInterval(
      Application.bind(this, this.checkForSeeking),
      this.seekCheckInterval);
};

Ads.prototype.updateCurrentTime = function() {
  if (!this.seeking) {
    this.currentTime = this.videoPlayer_.contentPlayer.currentTime;
  }
};

Ads.prototype.checkForSeeking = function() {
  var currentTime = this.videoPlayer_.contentPlayer.currentTime;
  // How much time has passed since you last ran this method, in milliseconds
  var diff = (currentTime - this.previousTime) * 1000;
  // If that difference is greater than the time since you last ran this method,
  // plus the threshold, the user was seeking
  if (Math.abs(diff)  > this.interval + this.threshold) {
    this.seeking = true;
  } else {
    this.seeking = false;
  }
  // Grab the current video time again to make up for time spent in this method
  previousTime = this.videoPlayer_.contentPlayer.currentTime;
};

Ads.prototype.onAdsManagerLoaded_ = function(adsManagerLoadedEvent) {
  this.application_.log('Ads loaded.');
  this.adsManager_ = adsManagerLoadedEvent.getAdsManager(this);
  this.processAdsManager_(this.adsManager_);
};

经过这些更改,SDK 现在使用 Ads 对象的 currentTime 属性来确定何时播放广告插播时间点,而不是内容视频播放器的 currentTime 属性。