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 proporcionar compatibilidad con un conjunto diferente de formatos.
| Formato de imagen | Compatible | Notas |
|---|---|---|
| BMP | SÍ | |
| GIF | NO | Sin compatibilidad con Extractor |
| JPEG | SÍ | |
| Foto en movimiento JPEG | SÍ | Se admiten imágenes congeladas y videos |
| JPEG Ultra HDR | SÍ | Se revierte a SDR en versiones anteriores a Android 14 o en pantallas que no son HDR. |
| PNG | SÍ | |
| WebP | SÍ | |
| HEIF/HEIC | SÍ | |
| Foto en movimiento HEIC | Parcialmente | Solo se admite una imagen fija* |
| AVIF (básico) | SÍ | 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 objeto MediaItem con el URI de la imagen y pásalo al reproductor. El objeto MediaItem debe tener un objeto 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 te ofrece varias formas de adaptar la experiencia de reproducción a las necesidades de tu app. Consulta la página Personalización para ver ejemplos.
Bibliotecas de carga de imágenes
Las imágenes suelen administrarse con bibliotecas externas de carga de imágenes, por ejemplo, Glide o Coil.
Para integrar estas bibliotecas en la canalización de reproducción, se requieren 3 pasos:
- Define un
MediaItemcon el tipo de MIMEAPPLICATION_EXTERNALLY_LOADED_IMAGE. - Proporciona un decodificador de imágenes para recuperar un
Bitmapde la biblioteca de carga de imágenes. - Proporciona un cargador externo para activar el almacenamiento en caché y la carga previa.
MediaItem con tipo de MIME de imagen cargada 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 del 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 que usa una biblioteca de carga de imágenes
El renderizador de imágenes necesita un ExternallyLoadedImageDecoder para recuperar el Bitmap del Uri. Este decodificador se puede proporcionar anulando DefaultRenderersFactory.getImageDecoderFactory.
En el siguiente ejemplo, se usa Glide para cargar una imagen y se limita el resultado al tamaño de la pantalla para evitar la creación de objetos Bitmap muy 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();
Precarga de imágenes con una biblioteca de carga de imágenes
Durante la reproducción, el reproductor solicita la precarga de la siguiente imagen una vez que se cargó por completo el elemento anterior de la playlist. Cuando usas una biblioteca externa de carga de imágenes, debes especificar un ExternalLoader para activar esta precarga. Si no es posible o necesario realizar una precarga, se debe proporcionar este cargador, pero no es necesario que haga nada.
En el siguiente ejemplo, se usa Glide para garantizar que la imagen solicitada se precargue 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) ) } 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();