HLS

ExoPlayer รองรับ HLS ที่มีรูปแบบคอนเทนเนอร์หลายรูปแบบ นอกจากนี้ รูปแบบของตัวอย่างเสียงและวิดีโอที่รวมอยู่ด้วยต้องได้รับการรองรับด้วย (ดูรายละเอียดในส่วนรูปแบบของตัวอย่าง) เราขอแนะนำให้ผู้ผลิตเนื้อหา HLS สร้างสตรีม HLS คุณภาพสูงตามที่อธิบายไว้ที่นี่

ฟีเจอร์ รองรับ ความคิดเห็น
คอนเทนเนอร์
MPEG-TS ใช่
FMP4/CMAF ใช่
ADTS (AAC) ใช่
MP3 ใช่
คำบรรยายแทนเสียง/คำบรรยายวิดีโอ
CEA-608 ใช่
CEA-708 ใช่
WebVTT ใช่
ข้อมูลเมตา
ID3 ใช่
SCTE-35 ไม่
การปกป้องเนื้อหา
AES-128 ใช่
ตัวอย่าง AES-128 ไม่
Widevine ใช่ API 19+ ("รูปแบบ cenc") และ 25+ ("รูปแบบ cbcs")
PlayReady SL2000 ใช่ Android TV เท่านั้น
การควบคุมเซิร์ฟเวอร์
การอัปเดต Delta ใช่
การบล็อกการโหลดเพลย์ลิสต์ซ้ำ ใช่
การบล็อกการโหลดคำแนะนำในการโหลดล่วงหน้า ใช่ ยกเว้นช่วงไบต์ที่มีความยาวที่ไม่ระบุ
การเล่นแบบสด
การเล่นแบบสดปกติ ใช่
HLS แบบเวลาในการตอบสนองต่ำ (Apple) ใช่
HLS แบบเวลาในการตอบสนองต่ำ (ชุมชน) ไม่
Common Media Client Data (CMCD) ใช่ คู่มือการผสานรวม

การใช้ MediaItem

หากต้องการเล่นสตรีม HLS คุณต้องใช้โมดูล HLS

Kotlin

implementation("androidx.media3:media3-exoplayer-hls:1.5.0")

Groovy

implementation "androidx.media3:media3-exoplayer-hls:1.5.0"

จากนั้นคุณจะสร้าง MediaItem สำหรับ URI ของเพลย์ลิสต์ HLS และส่งไปยังโปรแกรมเล่นได้

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri))
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri));
// Prepare the player.
player.prepare();

หาก URI ไม่ได้ลงท้ายด้วย .m3u8 คุณสามารถส่ง MimeTypes.APPLICATION_M3U8 ไปยัง setMimeType ของ MediaItem.Builder เพื่อระบุประเภทเนื้อหาอย่างชัดเจน

URI ของรายการสื่ออาจชี้ไปยังเพลย์ลิสต์สื่อหรือเพลย์ลิสต์เวอร์ชันหลายตัวแปร หาก URI ชี้ไปยังเพลย์ลิสต์แบบหลายตัวแปรที่ประกาศแท็ก #EXT-X-STREAM-INF หลายรายการ ExoPlayer จะปรับระหว่างตัวแปรต่างๆ โดยอัตโนมัติ โดยพิจารณาทั้งแบนด์วิดท์ที่มีอยู่และความสามารถของอุปกรณ์

การใช้ HlsMediaSource

หากต้องการตัวเลือกการปรับแต่งเพิ่มเติม คุณสามารถสร้าง HlsMediaSource แล้วส่งให้กับเพลเยอร์โดยตรงแทน MediaItem

Kotlin

// Create a data source factory.
val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory()
// Create a HLS media source pointing to a playlist uri.
val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri))
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri));
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource);
// Prepare the player.
player.prepare();

การเข้าถึงไฟล์ Manifest

คุณสามารถเรียกข้อมูลไฟล์ Manifest ฉบับปัจจุบันได้โดยเรียกใช้ Player.getCurrentManifest สำหรับ HLS คุณควรแคสต์ออบเจ็กต์ที่แสดงผลเป็น HlsManifest ระบบจะเรียกใช้ Callback onTimelineChanged ของ Player.Listener ทุกครั้งที่โหลดไฟล์ Manifest ด้วย การดำเนินการนี้จะเกิดขึ้น 1 ครั้งสำหรับเนื้อหาแบบออนดีมานด์ และอาจเกิดขึ้นหลายครั้งสำหรับเนื้อหาสด ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่แอปสามารถดำเนินการเมื่อใดก็ตามที่มีการโหลดไฟล์ Manifest

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
      val manifest = player.currentManifest
      if (manifest is HlsManifest) {
        // Do something with the manifest.
      }
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTimelineChanged(
          Timeline timeline, @Player.TimelineChangeReason int reason) {
        Object manifest = player.getCurrentManifest();
        if (manifest != null) {
          HlsManifest hlsManifest = (HlsManifest) manifest;
          // Do something with the manifest.
        }
      }
    });

การปรับแต่งการเล่น

ExoPlayer มีวิธีต่างๆ ในการปรับแต่งประสบการณ์การเล่นให้เหมาะกับความต้องการของแอป ดูตัวอย่างได้ที่หน้าการปรับแต่ง

การปิดใช้การเตรียมแบบไม่มีข้อมูลโค้ด

โดยค่าเริ่มต้น ExoPlayer จะใช้การเตรียมแบบไม่มีข้อมูลโค้ด ซึ่งหมายความว่า ExoPlayer จะใช้เฉพาะข้อมูลในเพลย์ลิสต์แบบหลายตัวแปรเพื่อเตรียมสตรีม ซึ่งจะใช้งานได้หากแท็ก #EXT-X-STREAM-INF มีแอตทริบิวต์ CODECS

คุณอาจต้องปิดใช้ฟีเจอร์นี้หากกลุ่มสื่อมีแทร็กคำบรรยายแทนเสียงที่มัลติเพลเยอร์ประกาศไว้ด้วยแท็ก #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS มิเช่นนั้น ระบบจะไม่ตรวจหาและเล่นแทร็กคำบรรยายแทนเสียงเหล่านี้ คุณสามารถปิดใช้การเตรียมแบบไม่แบ่งกลุ่มได้ใน HlsMediaSource.Factory ดังที่แสดงในข้อมูลโค้ดต่อไปนี้ โปรดทราบว่าการดำเนินการนี้จะเพิ่มเวลาเริ่มต้น เนื่องจาก ExoPlayer จำเป็นต้องดาวน์โหลดกลุ่มสื่อเพื่อค้นหาแทร็กเพิ่มเติมเหล่านี้ และคุณควรประกาศแทร็กคำบรรยายแทนในเพลย์ลิสต์แบบหลายตัวแปร

Kotlin

val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory)
    .setAllowChunklessPreparation(false)
    .createMediaSource(MediaItem.fromUri(hlsUri))

Java

HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory)
        .setAllowChunklessPreparation(false)
        .createMediaSource(MediaItem.fromUri(hlsUri));

การสร้างเนื้อหา HLS ที่มีคุณภาพสูง

คุณสามารถทำตามหลักเกณฑ์บางอย่างเพื่อปรับปรุงเนื้อหา HLS เพื่อให้ ExoPlayer ทำงานได้เต็มประสิทธิภาพ อ่านโพสต์ Medium เกี่ยวกับการเล่น HLS ใน ExopLayer เพื่อดูคำอธิบายทั้งหมด ประเด็นหลักๆ มีดังนี้

  • ใช้ระยะเวลาของกลุ่มที่แม่นยำ
  • ใช้สตรีมสื่อแบบต่อเนื่อง หลีกเลี่ยงการเปลี่ยนแปลงโครงสร้างสื่อในแต่ละกลุ่ม
  • ใช้แท็ก #EXT-X-INDEPENDENT-SEGMENTS
  • แนะนำให้ใช้สตรีมที่แยกข้อมูลแล้ว แทนไฟล์ที่มีทั้งวิดีโอและเสียง
  • ระบุข้อมูลทั้งหมดที่คุณทำได้ในเพลย์ลิสต์เวอร์ชันหลายตัวแปร

หลักเกณฑ์ต่อไปนี้ใช้กับสตรีมแบบสดโดยเฉพาะ

  • ใช้แท็ก #EXT-X-PROGRAM-DATE-TIME
  • ใช้แท็ก #EXT-X-DISCONTINUITY-SEQUENCE
  • แสดงเนื้อหาเป็นเวลานาน อย่างน้อย 1 นาทีก็เยี่ยมแล้ว