Imagens

O ExoPlayer é compatível com os seguintes formatos de imagem. Consulte Bibliotecas de carregamento de imagens para saber como integrar bibliotecas externas que podem oferecer suporte a um conjunto diferente de formatos.

Formato da imagem Compatível Observações
BMP SIM
GIF NÃO Sem suporte para extrator
JPEG SIM
Foto em movimento JPEG SIM Imagens estáticas e vídeos são aceitos
JPEG Ultra HDR SIM Volta para SDR antes do Android 14 ou em telas não HDR
PNG SIM
WebP SIM
HEIF/HEIC SIM
Foto com movimento HEIC Parcialmente Apenas imagens estáticas são aceitas*
AVIF (referência) SIM Decodificado apenas no Android 14 e versões mais recentes

* A parte de vídeo das fotos dinâmicas HEIC pode ser obtida com MetadataRetriever e reproduzida como um arquivo independente.

Usar MediaItem

Para reproduzir uma imagem como parte de uma playlist, crie um MediaItem com o URI da imagem e transmita-o ao player. O MediaItem precisa ter um imageDurationMs para especificar por quanto tempo a imagem deve ser exibida.

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

Fotos com movimento

As fotos com movimento são arquivos que combinam uma imagem estática com um vídeo curto.

  • Se a duração da imagem for definida com setImageDuration, a foto com movimento será mostrada pelo período declarado como uma imagem estática.
  • Se a duração da imagem não estiver definida, a foto com movimento será reproduzida como um vídeo.

Como usar ProgressiveMediaSource

Para mais opções de personalização, crie um ProgressiveMediaSource e transmita diretamente para o player em vez de um 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();

Personalizar a reprodução

O ExoPlayer oferece várias maneiras de personalizar a experiência de reprodução de acordo com as necessidades do seu app. Consulte a página de personalização para ver exemplos.

Bibliotecas de carregamento de imagens

As imagens geralmente são gerenciadas por bibliotecas externas de carregamento de imagens, como Glide ou Coil.

A integração dessas bibliotecas ao pipeline de reprodução exige três etapas:

  1. Defina um MediaItem com o tipo MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. Forneça um decodificador de imagem para recuperar um Bitmap da biblioteca de carregamento de imagens.
  3. Forneça um carregador externo para acionar o cache e o pré-carregamento.

MediaItem com tipo MIME de imagem carregada externamente

O MediaItem adicionado ao Player precisa definir explicitamente o tipo MIME APPLICATION_EXTERNALLY_LOADED_IMAGE para usar os caminhos de código da biblioteca de carregamento de imagens:

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

Decodificador de imagem usando uma biblioteca de carregamento de imagens

O renderizador de imagens precisa de um ExternallyLoadedImageDecoder para extrair o Bitmap do Uri. Esse decodificador pode ser fornecido substituindo DefaultRenderersFactory.getImageDecoderFactory.

O exemplo a seguir usa o Glide para carregar uma imagem, limitando a saída ao tamanho da tela para evitar a criação de objetos Bitmap muito grandes:

Kotlin

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

Java

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

Pré-carregamento de imagens com uma biblioteca de carregamento de imagens

Durante a reprodução, o player solicita o pré-carregamento da próxima imagem assim que o item anterior na playlist é totalmente carregado. Ao usar uma biblioteca externa de carregamento de imagens, especifique um ExternalLoader para acionar o pré-carregamento. Se nenhum pré-carregamento for possível ou necessário, esse carregador ainda precisará ser fornecido, mas não fará nada.

O exemplo a seguir usa o Glide para garantir que a imagem solicitada seja pré-carregada no disco:

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