HLS

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

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

การใช้ MediaItem

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

Kotlin

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

ดึงดูด

implementation "androidx.media3:media3-exoplayer-hls:1.4.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 กรณีนี้จะเกิดขึ้นครั้งเดียวสำหรับเนื้อหาแบบออนดีมานด์และ อาจหลายต่อหลายครั้งสำหรับเนื้อหาสด ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีที่แอป ทำอะไรบางอย่างได้ทุกครั้งที่ไฟล์ 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 คุณภาพสูง

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

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

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

  • ใช้แท็ก #EXT-X-PROGRAM-DATE-TIME
  • ใช้แท็ก #EXT-X-DISCONTINUITY-SEQUENCE
  • สร้างกรอบเวลาที่คงอยู่ยาวนาน 1 นาทีขึ้นไปกำลังดี