预加载媒体

IMA SDK 支持预加载视频广告素材资源。 您可以在 SDK 集成中启用此功能,以便在广告和内容之间实现更顺畅的转换。本指南介绍了使用 IMA SDK 实现媒体预加载的技术细节。

前提条件

预加载需要 IMA Android SDK 3.17.0 或更高版本。

启用预加载

如需启用预加载,请使用 AdsRenderingSettings.setEnablePreloading() 将预加载设置为 true。此操作必须在 onAdsManagerLoaded() 回调中完成:

@Override
public void onAdsManagerLoaded(AdsManagerLoadedEvent adsManagerLoadedEvent) {
  ...
  AdsRenderingSettings adsRenderingSettings =
      ImaSdkFactory.getInstance().createAdsRenderingSettings();
  adsRenderingSettings.setEnablePreloading(true);
  mAdsManager.init(adsRenderingSettings);
}

使用自定义 VideoAdPlayer 支持预加载

我们建议您使用 Android ExoPlayer 示例应用中使用的 ExoPlayer-IMA 扩展程序。集成后,ExoPlayer-IMA 扩展程序会默认启用预加载,并包含内置的预加载支持。

如果您在不使用 ExoPlayer-IMA 扩展程序的情况下实现预加载,则需要在调用 setEnablePreloading() 后进行其他更改。为了支持预加载广告,视频播放器必须跟踪从 loadAd()playAd() 调用中传递的 AdMediaInfo 对象,并在 AdPlayerCallback 调用中包含正确的 AdMediaInfo。鉴于在当前正在播放之前的 AdMediaInfo 时,可能会发生后续 AdMediaInfoloadAd(),因此这可能需要使用数据结构来管理 AdMediaInfo 对象。以下示例展示了您可能需要进行的一些更改,以便应用支持预加载:

// enum for cases of PlayerState.
static enum PlayerState {
  IDLE,
  LOADED,
  PLAYING,
  PAUSED,
}

...

private final List<VideoAdPlayer.VideoAdPlayerCallback> callbacks;
private final ArrayList<AdMediaInfo> mediaInfos = new ArrayList<>();
private PlayerState playerState;
private boolean adCurrentlyLoaded;

...

@Override
public void playAd(AdMediaInfo adMediaInfo) {
  switch (playerState) {
    case LOADED:
      for (VideoAdPlayerCallback callback : callbacks) {
        callback.onPlay(adMediaInfo);
      }
      break;
    case PAUSED:
      for (VideoAdPlayerCallback callback : callbacks) {
        callback.onResume(adMediaInfo);
      }
      break;
    case PLAYING:
      // Intentionally and silently ignore since it is already playing from a prior media item,
      // note that onPlay is triggered by positionDiscontinuity.
      return;
    case IDLE:
      throw new IllegalStateException("Call to playAd when player state is not LOADED.");
  }
  playerState = PlayerState.PLAYING;
  player.setPlayWhenReady(true);
}

@Override
public void loadAd(AdMediaInfo adMediaInfo, AdPodInfo adPodInfo) {
  if (adCurrentlyLoaded == true) {
    mediaInfos.add(adMediaInfo);
    return;
  }
  player.stop();
  player.seekTo(0);
  mediaInfos.clear();
  mediaInfos.add(adMediaInfo);
  player.setPlayWhenReady(false);
  player.loadMedia(adMediaInfo.getUrl());
  playerState = PlayerState.LOADED;
  adCurrentlyLoaded = true;
}

@Override
public void stopAd(AdMediaInfo adMediaInfo) {
  if (allAdsInBreakHavePlayed()) {
    if (isFinalAd(adMediaInfo)) {
      // handle clean up after all ads have played.
    } else {
      seekToNextItem(player);
    }
  } else {
    mediaInfos.remove(adMediaInfo);
  }
}

private boolean allAdsInBreakHavePlayed() {
  // Code to determine if all the ads in the current ad break have completed.
}

private boolean isFinalAd(AdMediaInfo adMediaInfo) {
  // Code to determine if this adMediaInfo is the final ad.
}

private void seekToNextItem(YourPlayerClass player) {
  // Code to seek your player to the next media item.
}

测试自定义预加载实现

对于自定义预加载实现,建议测试以下极端情况,以验证预加载设置是否正确:

  • 单个前贴片广告
  • 3 个广告连播前贴片广告
  • 3 个广告连播中贴片广告
  • 在第一个中贴片广告开始预加载但尚未播放时跳转到第二个中贴片广告
  • 后贴片广告播放

计时

下表总结了启用预加载后广告加载时间的变化:

事件 带预加载 不预加载
请求的广告 VAST AdsLoader.requestAds() AdsLoader.requestAds()
前贴片广告已加载(单个广告) AdsManager.init() AdsManager.start()
已加载前贴片广告 (VMAP/广告规则) AdsManager.init() AdsManager.init()
加载了中贴片广告或后贴片广告 对于广告插播时段中的第一个广告,应在广告开始播放前 8 秒。 对于连续广告,是在前一广告开始播放时。 在广告开始播放时。

常见问题解答

媒体预加载是否会加载完整广告素材?
不可以,广告开始播放时,广告素材通常尚未完全加载。预加载旨在通过最大限度缩短广告加载时间来改善用户体验。它不支持离线广告投放。
是否需要为广告的 VAST 和媒体启用媒体预加载?
否,无论此预加载设置如何,SDK 始终会预加载广告的 VAST。