圖片
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
ExoPlayer 支援下列圖片格式。如要瞭解如何整合可能支援不同格式的外部程式庫,請參閱「圖片載入程式庫」。
圖片格式 |
支援 |
附註 |
BMP |
是 |
|
GIF |
否 |
不支援 Extractor |
JPEG |
是 |
|
JPEG 動態相片 |
是 |
支援靜態影像和影片 |
JPEG Ultra HDR
|
是 |
在 Android 14 之前或非 HDR 螢幕上,會改用 SDR |
PNG |
是 |
|
WebP |
是 |
|
HEIF/HEIC |
是 |
|
HEIC 動態相片 |
不盡然 |
僅支援靜態圖片* |
AVIF (基準) |
是 |
僅在 Android 14 以上版本解碼 |
* 您可以使用 MetadataRetriever 取得 HEIC 動態相片的影片部分,並以獨立檔案播放。
如要播放圖片做為播放清單的一部分,請使用圖片 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
,並直接將其傳遞給播放器,而非 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 提供多種方式,讓您依據應用程式需求調整播放體驗。如需範例,請參閱自訂頁面。
圖片載入程式庫
圖片通常由外部圖片載入程式庫管理,例如 Glide 或 Coil。
將這些程式庫整合至播放管道需要 3 個步驟:
- 使用
APPLICATION_EXTERNALLY_LOADED_IMAGE
MIME 類型定義 MediaItem
。
- 提供圖片解碼器,從圖片載入程式庫中擷取
Bitmap
。
- 提供外部載入器,觸發快取和預先載入。
使用外部載入圖片 MIME 類型的 MediaItem
新增至 Player
的 MediaItem
必須明確定義 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();
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Images\n\nExoPlayer supports the following image formats. See\n[Image Loading Libraries](/media/media3/exoplayer/images#image-loading-libraries)\nfor how to integrate with external libraries that may provide support for a\ndifferent set of formats.\n\n| Image format | Supported | Notes |\n|-------------------|-----------|------------------------------------------------------------|\n| BMP | YES | |\n| GIF | NO | No Extractor support |\n| JPEG | YES | |\n| JPEG Motion Photo | YES | Still image and video supported |\n| JPEG Ultra HDR | YES | Falls back to SDR before Android 14 or on non-HDR displays |\n| PNG | YES | |\n| WebP | YES | |\n| HEIF/HEIC | YES | |\n| HEIC Motion Photo | Partially | Only still image supported\\* |\n| AVIF (baseline) | YES | Decoded on Android 14+ only |\n\n\\* The video part of HEIC motion photos can be obtained with\n[MetadataRetriever](/media/media3/exoplayer/retrieving-metadata#motion-photos)\nand played as a standalone file.\n\nUsing MediaItem\n---------------\n\nTo play an image as part of a playlist, create a `MediaItem` with the image URI\nand pass it to the player. The `MediaItem` must have a `imageDurationMs` to\nspecify for how long the image should be displayed. \n\n### Kotlin\n\n```kotlin\n// Create a player instance.\nval player = ExoPlayer.Builder(context).build()\n// Set the media item to be played with the desired duration.\nplayer.setMediaItem(\n MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build())\n// Prepare the player.\nplayer.prepare()\n```\n\n### Java\n\n```java\n// Create a player instance.\nExoPlayer player = new ExoPlayer.Builder(context).build();\n// Set the media item to be played with the desired duration.\nplayer.setMediaItem(\n new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build());\n// Prepare the player.\nplayer.prepare();\n```\n\n\u003cbr /\u003e\n\n### Motion Photos\n\nMotion photos are files combining a still image with a short video.\n\n- If the image duration is defined with `setImageDuration`, the motion photo is displayed for the declared duration as a still image.\n- If the image duration is undefined, the motion photo is played as a video.\n\nUsing ProgressiveMediaSource\n----------------------------\n\nFor more customization options, you can create a `ProgressiveMediaSource` and\npass it directly to the player instead of a `MediaItem`. \n\n### Kotlin\n\n```kotlin\n// Create a data source factory.\nval dataSourceFactory = DefaultHttpDataSource.Factory()\n// Create a media item with the image URI and the desired duration.\nval mediaItem =\n MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build()\n// Create a progressive media source for this media item.\nval mediaSource =\n ProgressiveMediaSource.Factory(dataSourceFactory)\n .createMediaSource(mediaItem)\n// Create a player instance.\nval player = ExoPlayer.Builder(context).build()\n// Set the media source to be played.\nplayer.setMediaSource(mediaSource)\n// Prepare the player.\nplayer.prepare()\n```\n\n### Java\n\n```java\n// Create a data source factory.\nDataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();\n// Create a media item with the image URI and the desired duration.\nMediaItem mediaItem =\n new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build();\n// Create a progressive media source for this media item.\nMediaSource mediaSource =\n new ProgressiveMediaSource.Factory(dataSourceFactory)\n .createMediaSource(mediaItem);\n// Create a player instance.\nExoPlayer player = new ExoPlayer.Builder(context).build();\n// Set the media source to be played.\nplayer.setMediaSource(mediaSource);\n// Prepare the player.\nplayer.prepare();\n```\n\n\u003cbr /\u003e\n\nCustomizing playback\n--------------------\n\nExoPlayer provides multiple ways for you to tailor playback experience to your\napp's needs. See the [Customization page](/guide/topics/media/exoplayer/customization) for examples.\n\nImage Loading Libraries\n-----------------------\n\nImages are often managed by external image loading libraries, for example\n[Glide](https://bumptech.github.io/glide/) or\n[Coil](https://coil-kt.github.io/coil/).\n\nIntegrating these libraries into the playback pipeline requires 3 steps:\n\n1. Define a `MediaItem` with `APPLICATION_EXTERNALLY_LOADED_IMAGE` MIME type.\n2. Provide an image decoder to retrieve a `Bitmap` from the image loading library.\n3. Provide an external loader to trigger caching and preloading.\n\n### MediaItem with externally loaded image MIME type\n\nThe `MediaItem` added to the `Player` must define the\n`APPLICATION_EXTERNALLY_LOADED_IMAGE` MIME type explicitly to use the image\nloading library code paths: \n\n### Kotlin\n\n```kotlin\nval mediaItem =\n MediaItem.Builder()\n .setUri(imageUri)\n .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)\n .build()\n```\n\n### Java\n\n```java\nMediaItem mediaItem =\n new MediaItem.Builder()\n .setUri(imageUri)\n .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)\n .build();\n```\n\n\u003cbr /\u003e\n\n### Image decoder using an image loading library\n\nThe image renderer needs an `ExternallyLoadedImageDecoder` to retrieve the\n`Bitmap` from the `Uri`. This decoder can be provided by overriding\n`DefaultRenderersFactory.getImageDecoderFactory`.\n\nThe following example uses Glide to load an image: \n\n### Kotlin\n\n```kotlin\nval glideImageDecoderFactory: ImageDecoder.Factory =\n ExternallyLoadedImageDecoder.Factory { request: ExternalImageRequest -\u003e\n GlideFutures.submit(Glide.with(context).asBitmap().load(request.uri))\n }\nval player: Player =\n ExoPlayer.Builder(context)\n .setRenderersFactory(\n object : DefaultRenderersFactory(context) {\n override fun getImageDecoderFactory(): ImageDecoder.Factory {\n return glideImageDecoderFactory\n }\n }\n )\n .build()\n```\n\n### Java\n\n```java\nImageDecoder.Factory glideImageDecoderFactory =\n new ExternallyLoadedImageDecoder.Factory(\n request -\u003e GlideFutures.submit(\n Glide.with(context).asBitmap().load(request.uri)));\nPlayer player =\n new ExoPlayer.Builder(context)\n .setRenderersFactory(\n new DefaultRenderersFactory(context) {\n @Override\n protected ImageDecoder.Factory getImageDecoderFactory() {\n return glideImageDecoderFactory;\n }\n })\n .build();\n```\n\n\u003cbr /\u003e\n\n### Image preloading with an image loading library\n\nDuring playback, the player requests to preload the next image once the previous\nitem in the playlist has fully loaded. When using an external image loading\nlibrary, you must specify an `ExternalLoader` to trigger this preloading. If no\npreloading is possible or required, this loader still needs to be provided, but\ncan do nothing.\n\nThe following example uses Glide to ensure that the requested image is preloaded\nto disk: \n\n### Kotlin\n\n```kotlin\nval glidePreloader = ExternalLoader { request: LoadRequest -\u003e\n GlideFutures.submit(\n Glide.with(context)\n .asFile()\n .apply(\n RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA)\n .priority(Priority.HIGH)\n .skipMemoryCache(true)\n )\n .load(request.uri)\n )\n}\nval player =\n ExoPlayer.Builder(context)\n .setMediaSourceFactory(DefaultMediaSourceFactory(context)\n .setExternalImageLoader(glidePreloader))\n .build()\n```\n\n### Java\n\n```java\nExternalLoader glidePreloader =\n request -\u003e\n GlideFutures.submit(\n Glide.with(context)\n .asFile()\n .apply(\n diskCacheStrategyOf(DiskCacheStrategy.DATA)\n .priority(Priority.HIGH)\n .skipMemoryCache(true))\n .load(request.uri));\nPlayer player =\n new ExoPlayer.Builder(context)\n .setMediaSourceFactory(new DefaultMediaSourceFactory(context)\n .setExternalImageLoader(glidePreloader))\n .build();\n```\n\n\u003cbr /\u003e"]]