Images

ExoPlayer admite los siguientes formatos de imagen. Consulta Bibliotecas de carga de imágenes para obtener información sobre cómo realizar la integración con bibliotecas externas que pueden admitir un conjunto diferente de formatos.

Formato de imagen Compatible Notas
BMP
GIF NO No es compatible con Extractor
JPEG
Foto en movimiento JPEG Se admiten imágenes fijas y videos
JPEG Ultra HDR Recurre a SDR antes de Android 14 o en pantallas que no son HDR.
PNG
WebP
HEIF/HEIC
Foto en movimiento HEIC Parcialmente Solo se admiten imágenes fijas*
AVIF (referencia) Solo se decodifica en Android 14 y versiones posteriores

* La parte de video de las fotos en movimiento HEIC se puede obtener con MetadataRetriever y reproducir como un archivo independiente.

Cómo usar MediaItem

Para reproducir una imagen como parte de una playlist, crea un MediaItem con el URI de la imagen y pásalo al reproductor. MediaItem debe tener un imageDurationMs para especificar durante cuánto tiempo se debe mostrar la imagen.

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 en movimiento

Las fotos en movimiento son archivos que combinan una imagen fija con un video corto.

  • Si la duración de la imagen se define con setImageDuration, la foto en movimiento se muestra durante la duración declarada como una imagen fija.
  • Si la duración de la imagen no está definida, la foto en movimiento se reproduce como un video.

Cómo usar ProgressiveMediaSource

Para obtener más opciones de personalización, puedes crear un ProgressiveMediaSource y pasarlo directamente al reproductor en lugar de un 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();

Cómo personalizar la reproducción

ExoPlayer ofrece varias formas de personalizar la experiencia de reproducción según las necesidades de tu app. Consulta la página Personalización para ver ejemplos.

Bibliotecas de carga de imágenes

A menudo, las imágenes se administran con bibliotecas externas de carga de imágenes, por ejemplo, Glide o Coil.

La integración de estas bibliotecas en la canalización de reproducción requiere 3 pasos:

  1. Define un MediaItem con el tipo de MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. Proporciona un decodificador de imágenes para recuperar un Bitmap de la biblioteca de carga de imágenes.
  3. Proporciona un cargador externo para activar la caché y la carga previa.

MediaItem con un tipo de MIME de imagen cargado de forma externa

El MediaItem agregado al Player debe definir el tipo de MIME APPLICATION_EXTERNALLY_LOADED_IMAGE de forma explícita para usar las rutas de acceso de código de la biblioteca de carga de imágenes:

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 imágenes con una biblioteca de carga de imágenes

El renderizador de imágenes necesita un ExternallyLoadedImageDecoder para recuperar el Bitmap de Uri. Para proporcionar este decodificador, anula DefaultRenderersFactory.getImageDecoderFactory.

En el siguiente ejemplo, se usa Glide para cargar una imagen:

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

Carga previa de imágenes con una biblioteca de carga de imágenes

Durante la reproducción, el reproductor solicita la carga previa de la siguiente imagen una vez que se cargó por completo el elemento anterior de la playlist. Cuando usas una biblioteca de carga de imágenes externa, debes especificar un ExternalLoader para activar esta carga previa. Si no es posible o no se requiere la carga previa, este cargador aún debe proporcionarse, pero no puede hacer nada.

En el siguiente ejemplo, se usa Glide para garantizar que la imagen solicitada se cargue previamente en el 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)
  )
}

Java

ExternalLoader glidePreloader =
    request ->
        GlideFutures.submit(
            Glide.with(context)
                .asFile()
                .apply(
                    diskCacheStrategyOf(DiskCacheStrategy.DATA)
                        .priority(Priority.HIGH)
                        .skipMemoryCache(true))
                .load(request.uri));