Изображения

ExoPlayer поддерживает следующие форматы изображений. Подробнее об интеграции с внешними библиотеками, которые могут поддерживать другие форматы, см. в разделе «Библиотеки загрузки изображений».

Формат изображения Поддерживается Примечания
БМП ДА
GIF НЕТ Нет поддержки Extractor
JPEG ДА
JPEG-фото движения ДА Поддерживаются неподвижные изображения и видео
JPEG Ультра HDR ДА Возвращается к SDR до Android 14 или на дисплеях без HDR
PNG ДА
WebP ДА
HEIF/HEIC ДА
HEIC Motion Photo Частично Поддерживаются только неподвижные изображения*
AVIF (базовый) ДА Декодируется только на Android 14+

* Видеочасть фотографий движения HEIC можно получить с помощью MetadataRetriever и воспроизвести как отдельный файл.

Использование MediaItem

Чтобы воспроизвести изображение из плейлиста, создайте MediaItem с URI изображения и передайте его плееру. У MediaItem должно быть свойство imageDurationMs , определяющее длительность отображения изображения.

Котлин

// 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()

Ява

// 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 .

Котлин

// 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()

Ява

// 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 предоставляет множество способов настроить воспроизведение в соответствии с потребностями вашего приложения. Примеры см. на странице настроек .

Библиотеки загрузки изображений

Изображения часто управляются внешними библиотеками загрузки изображений, например Glide или Coil .

Интеграция этих библиотек в конвейер воспроизведения требует 3 шагов:

  1. Определите MediaItem с типом MIME APPLICATION_EXTERNALLY_LOADED_IMAGE .
  2. Предоставить декодер изображений для извлечения Bitmap из библиотеки загрузки изображений.
  3. Предоставить внешний загрузчик для запуска кэширования и предварительной загрузки.

MediaItem с внешним загруженным типом изображения MIME

Для использования путей кода библиотеки загрузки изображений в элементе MediaItem , добавленном в Player необходимо явно определить тип MIME APPLICATION_EXTERNALLY_LOADED_IMAGE :

Котлин

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

Ява

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

Декодер изображений с использованием библиотеки загрузки изображений

Для получения Bitmap изображения из Uri рендереру изображений необходим декодер ExternallyLoadedImageDecoder . Этот декодер можно получить, переопределив метод DefaultRenderersFactory.getImageDecoderFactory .

В следующем примере Glide используется для загрузки изображения, ограничивая вывод размером дисплея, чтобы избежать создания очень больших объектов Bitmap :

Котлин

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

Ява

ImageDecoder.Factory glideImageDecoderFactory =
    new ExternallyLoadedImageDecoder.Factory(
        request -> {
          Point displaySize = Util.getCurrentDisplayModeSize(context);
          return GlideFutures.submit(
            Glide.with(context)
                .asBitmap()
                .load(request.uri)
                .override(max(displaySize.x, displaySize.y)));
            });
Player player =
    new ExoPlayer.Builder(context)
        .setRenderersFactory(
            new DefaultRenderersFactory(context) {
              @Override
              protected ImageDecoder.Factory getImageDecoderFactory(Context context) {
                return glideImageDecoderFactory;
              }
            })
        .build();

Предварительная загрузка изображений с помощью библиотеки загрузки изображений

Во время воспроизведения плеер запрашивает предварительную загрузку следующего изображения после полной загрузки предыдущего элемента плейлиста. При использовании внешней библиотеки загрузки изображений необходимо указать загрузчик ExternalLoader для запуска этой предзагрузки. Если предварительная загрузка невозможна или не требуется, этот загрузчик всё равно необходимо предоставить, но он ничего не сделает.

В следующем примере Glide используется для обеспечения предварительной загрузки запрошенного изображения на диск:

Котлин

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()

Ява

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();