图片

ExoPlayer 支持以下图像格式。有关如何与可能提供不同格式集支持的外部库集成的详细信息,请参阅图像加载库

图像格式 支持 备注
BMP
GIF 不支持提取器
JPEG
JPEG Motion Photo 支持静态图像和视频
JPEG Ultra HDR 在 Android 14 之前或在非 HDR 显示器上回退到 SDR
PNG
WebP
HEIF/HEIC
HEIC Motion Photo 部分支持 仅支持静态图像*
AVIF(基线) 仅在 Android 14+ 上解码

* HEIC 动态照片的视频部分可以通过 MetadataRetriever 获取,并作为独立文件播放。

使用 MediaItem

要将图像作为播放列表的一部分播放,请使用图像 URI 创建一个 MediaItem 并将其传递给播放器。MediaItem 必须具有 imageDurationMs 以指定图像应显示多长时间。

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played with the desired duration.
player.setMediaItem(
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build())
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played with the desired duration.
player.setMediaItem(
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build());
// Prepare the player.
player.prepare();

动态照片

动态照片是结合了静态图像和短视频的文件。

  • 如果使用 setImageDuration 定义了图像持续时间,则动态照片将以静态图像形式显示指定持续时间。
  • 如果未定义图像持续时间,则动态照片将作为视频播放。

使用 ProgressiveMediaSource

如需更多自定义选项,您可以创建 ProgressiveMediaSource 并将其直接传递给播放器,而不是 MediaItem

Kotlin

// Create a data source factory.
val dataSourceFactory = DefaultHttpDataSource.Factory()
// Create a media item with the image URI and the desired duration.
val mediaItem =
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build()
// Create a progressive media source for this media item.
val mediaSource =
    ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem)
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media source to be played.
player.setMediaSource(mediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a media item with the image URI and the desired duration.
MediaItem mediaItem =
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build();
// Create a progressive media source for this media item.
MediaSource mediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem);
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(mediaSource);
// Prepare the player.
player.prepare();

自定义播放

ExoPlayer 提供了多种方式,让您可以根据应用的需求定制播放体验。有关示例,请参阅自定义页面

图像加载库

图像通常由外部图像加载库管理,例如 GlideCoil

将这些库集成到播放管道需要 3 个步骤

  1. 定义一个 MIME 类型为 APPLICATION_EXTERNALLY_LOADED_IMAGEMediaItem
  2. 提供一个图像解码器,以从图像加载库中检索 Bitmap
  3. 提供一个外部加载器来触发缓存和预加载。

具有外部加载图像 MIME 类型的 MediaItem

添加到 PlayerMediaItem 必须明确定义 APPLICATION_EXTERNALLY_LOADED_IMAGE MIME 类型,才能使用图像加载库的代码路径

Kotlin

val mediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
    .build()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
        .build();

使用图像加载库的图像解码器

图像渲染器需要 ExternallyLoadedImageDecoder 来从 Uri 检索 Bitmap。此解码器可以通过重写 DefaultRenderersFactory.getImageDecoderFactory 提供。

以下示例使用 Glide 加载图像

Kotlin

val glideImageDecoderFactory: ImageDecoder.Factory =
  ExternallyLoadedImageDecoder.Factory { request: ExternalImageRequest ->
    GlideFutures.submit(Glide.with(context).asBitmap().load(request.uri))
  }
val player: Player =
  ExoPlayer.Builder(context)
    .setRenderersFactory(
      object : DefaultRenderersFactory(context) {
        override fun getImageDecoderFactory(): ImageDecoder.Factory {
          return glideImageDecoderFactory
        }
      }
    )
    .build()

Java

ImageDecoder.Factory glideImageDecoderFactory =
    new ExternallyLoadedImageDecoder.Factory(
        request -> GlideFutures.submit(
            Glide.with(context).asBitmap().load(request.uri)));
Player player =
    new ExoPlayer.Builder(context)
        .setRenderersFactory(
            new DefaultRenderersFactory(context) {
              @Override
              protected ImageDecoder.Factory getImageDecoderFactory() {
                return glideImageDecoderFactory;
              }
            })
        .build();

使用图像加载库进行图像预加载

在播放期间,一旦播放列表中的上一个项目完全加载,播放器就会请求预加载下一个图像。当使用外部图像加载库时,您必须指定一个 ExternalLoader 来触发此预加载。如果不需要或不可能进行预加载,则仍需提供此加载器,但它可以不执行任何操作。

以下示例使用 Glide 确保请求的图像预加载到磁盘

Kotlin

val glidePreloader = ExternalLoader { request: LoadRequest ->
  GlideFutures.submit(
    Glide.with(context)
      .asFile()
      .apply(
        RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA)
          .priority(Priority.HIGH)
          .skipMemoryCache(true)
      )
      .load(request.uri)
  )
}
val player =
    ExoPlayer.Builder(context)
      .setMediaSourceFactory(DefaultMediaSourceFactory(context)
        .setExternalImageLoader(glidePreloader))
      .build()

Java

ExternalLoader glidePreloader =
    request ->
        GlideFutures.submit(
            Glide.with(context)
                .asFile()
                .apply(
                    diskCacheStrategyOf(DiskCacheStrategy.DATA)
                        .priority(Priority.HIGH)
                        .skipMemoryCache(true))
                .load(request.uri));
Player player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context)
            .setExternalImageLoader(glidePreloader))
        .build();