รูปภาพ

ExoPlayer รองรับรูปแบบรูปภาพต่อไปนี้ ดูวิธีผสานรวมกับไลบรารีภายนอกที่อาจรองรับชุดรูปแบบอื่นได้จากไลบรารีการโหลดรูปภาพ

รูปแบบรูปภาพ รองรับ หมายเหตุ
BMP ใช่
GIF ไม่ ไม่รองรับเครื่องมือแยก
JPEG ใช่
รูปภาพเคลื่อนไหว JPEG ใช่ รองรับรูปภาพนิ่งและวิดีโอ
JPEG Ultra HDR ใช่ เปลี่ยนกลับไปใช้ SDR ก่อน Android 14 หรือในจอแสดงผลที่ไม่ใช่ HDR
PNG ใช่
WebP ใช่
HEIF/HEIC ใช่
รูปภาพเคลื่อนไหว HEIC เพียงบางส่วน รองรับเฉพาะภาพนิ่ง*
AVIF (เบสไลน์) ใช่ ถอดรหัสได้ใน Android 14 ขึ้นไปเท่านั้น

* คุณดูส่วนวิดีโอของรูปภาพเคลื่อนไหว HEIC ได้โดยใช้ MetadataRetriever และเล่นเป็นไฟล์เดี่ยว

การใช้ MediaItem

หากต้องการเล่นรูปภาพเป็นส่วนหนึ่งของเพลย์ลิสต์ ให้สร้าง MediaItem ด้วย URI ของรูปภาพแล้วส่งไปยังโปรแกรมเล่น 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

หากต้องการตัวเลือกการปรับแต่งเพิ่มเติม คุณสามารถสร้าง 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 ขั้นตอนดังนี้

  1. กำหนด MediaItem ที่มีประเภท MIME APPLICATION_EXTERNALLY_LOADED_IMAGE
  2. ระบุโปรแกรมถอดรหัสรูปภาพเพื่อดึงข้อมูล Bitmap จากคลังการโหลดรูปภาพ
  3. ระบุโปรแกรมโหลดภายนอกเพื่อทริกเกอร์การแคชและการโหลดล่วงหน้า

MediaItem ที่มีประเภท MIME ของรูปภาพที่โหลดจากภายนอก

MediaItem ที่เพิ่มลงใน Player ต้องกำหนดประเภท MIME APPLICATION_EXTERNALLY_LOADED_IMAGE อย่างชัดเจนเพื่อใช้เส้นทางโค้ดของไลบรารีการโหลดรูปภาพ

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 เพื่อดึงข้อมูล Bitmap จาก Uri คุณสามารถระบุตัวถอดรหัสนี้ได้โดยการลบล้าง 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)
  )
}

Java

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