สตรีมมิงแบบสด

ExoPlayer เล่นสตรีมแบบสดที่ปรับเปลี่ยนให้เหมาะกับผู้ใช้มากที่สุดได้ทันทีตั้งแต่แกะกล่องโดยไม่มีอะไรพิเศษ การกำหนดค่า ดูรายละเอียดเพิ่มเติมในหน้ารูปแบบที่รองรับ

สตรีมแบบสดแบบปรับอัตโนมัติมีหน้าต่างสื่อที่พร้อมใช้งานที่อัปเดตใน ช่วงเวลาปกติที่จะเคลื่อนไหวตามเรียลไทม์ปัจจุบัน ซึ่งหมายความว่าการเล่น จะอยู่ไหนสักแห่งในหน้าต่างนี้เสมอ ซึ่งในกรณีส่วนใหญ่ แบบเรียลไทม์ในปัจจุบันที่มีการผลิตสตรีมอยู่ ความแตกต่างระหว่าง เรียลไทม์ปัจจุบันและตำแหน่งการเล่นเรียกว่าออฟเซ็ตแบบเรียลไทม์

การตรวจหาและการตรวจสอบการเล่นแบบสด

ทุกครั้งที่อัปเดตกรอบเวลาที่เผยแพร่อยู่ ระบบจะลงทะเบียนอินสแตนซ์ Player.Listener รายการ จะได้รับเหตุการณ์ onTimelineChanged คุณสามารถดูรายละเอียดเกี่ยวกับ การเล่นสตรีมแบบสดในปัจจุบันโดยค้นหา Player และ Timeline.Window ต่างๆ วิธีการตามที่ระบุไว้ด้านล่างและแสดงในรูปต่อไปนี้

หน้าต่างถ่ายทอดสด

  • Player.isCurrentWindowLive ระบุว่าสื่อที่เล่นอยู่ในขณะนี้หรือไม่ คือสตรีมแบบสด ค่านี้ยังคงเป็นจริง แม้ว่าสตรีมแบบสดจะมี สิ้นสุดแล้ว
  • Player.isCurrentWindowDynamic ระบุว่าสื่อที่เล่นอยู่ในขณะนี้หรือไม่ กำลังอัปเดตรายการ ซึ่งมักจะเป็นเช่นนี้สำหรับสตรีมแบบสดที่ ยังไม่สิ้นสุด โปรดทราบว่าการตั้งค่าสถานะจะเป็นจริงสำหรับสตรีมที่ไม่ใช่สตรีมแบบสดในบางกรณี กรณี
  • Player.getCurrentLiveOffset แสดงค่าออฟเซ็ตระหว่างค่าจริงปัจจุบัน เวลาและตำแหน่งการเล่น (หากมี)
  • Player.getDuration แสดงความยาวของกรอบเวลาที่เผยแพร่อยู่ในขณะนั้น
  • Player.getCurrentPosition คืนตำแหน่งการเล่นที่สัมพันธ์กับ ที่เริ่มต้นหน้าต่างแบบสด
  • Player.getCurrentMediaItem จะแสดงรายการสื่อปัจจุบัน โดยที่ MediaItem.liveConfiguration มีการลบล้างที่แอปให้ไว้สำหรับเป้าหมาย พารามิเตอร์การปรับออฟเซ็ตแบบเรียลไทม์และพารามิเตอร์การปรับออฟเซ็ตแบบเรียลไทม์
  • Player.getCurrentTimeline จะแสดงผลโครงสร้างสื่อปัจจุบันใน Timeline สามารถดึงข้อมูล Timeline.Window ปัจจุบันได้จาก Timeline โดยใช้ Player.getCurrentWindowIndex และ Timeline.getWindow ภายใน Window:
    • Window.liveConfiguration มีออฟเซ็ตแบบเรียลไทม์เป้าหมายและออฟเซ็ตแบบเรียลไทม์ พารามิเตอร์การปรับ ค่าเหล่านี้ขึ้นอยู่กับข้อมูลในสื่อ และการลบล้างที่แอปมีให้ที่ตั้งค่าไว้ใน MediaItem.liveConfiguration
    • Window.windowStartTimeMs เป็นเวลานับตั้งแต่ Unix Epoch ซึ่งมีเหตุการณ์ ช่วงถ่ายทอดสดเริ่มต้น
    • Window.getCurrentUnixTimeMs เป็นเวลานับตั้งแต่ Unix Epoch ของ แบบเรียลไทม์ในปัจจุบัน ค่านี้อาจแก้ไขได้โดยความแตกต่างของนาฬิกาที่รู้จัก ระหว่างเซิร์ฟเวอร์และไคลเอ็นต์
    • Window.getDefaultPositionMs คือตำแหน่งในหน้าต่างถ่ายทอดสดที่ โปรแกรมเล่นจะเริ่มเล่นโดยค่าเริ่มต้น

การค้นหาในสตรีมแบบสด

คุณสามารถค้นหาไปยังที่ใดก็ได้ภายในกรอบเวลาสดโดยใช้ Player.seekTo การค้นหา ตำแหน่งที่ผ่านไปจะสัมพันธ์กับจุดเริ่มต้นของหน้าต่างที่เผยแพร่อยู่ ตัวอย่างเช่น seekTo(0) จะกรอไปยังจุดเริ่มต้นของหน้าต่างที่เผยแพร่อยู่ โปรแกรมเล่นจะพยายาม ให้ออฟเซ็ตแบบเรียลไทม์เหมือนกันกับตำแหน่งสำหรับ "ค้นหา" หลังการกรอ

หน้าต่างถ่ายทอดสดยังมีตำแหน่งเริ่มต้นที่ควรเล่นวิดีโอ เริ่ม ตำแหน่งนี้มักจะอยู่ใกล้ขอบที่มีการใช้งานจริง คุณสามารถกรอวิดีโอ ไปยังตำแหน่งเริ่มต้นโดยเรียกใช้ Player.seekToDefaultPosition

UI การเล่นแบบสด

คอมโพเนนต์ UI เริ่มต้นของ ExoPlayer จะแสดงระยะเวลาของกรอบเวลาที่เผยแพร่อยู่และ ตำแหน่งการเล่นปัจจุบันภายในตำแหน่งนั้น ซึ่งหมายความว่าตำแหน่งจะปรากฏเป็น ย้อนกลับเมื่อมีการอัปเดตกรอบเวลาในการถ่ายทอดสด หากต้องการ ตัวอย่างเช่น แสดงเวลา Unix หรือออฟเซ็ตแบบเรียลไทม์ในปัจจุบัน คุณสามารถ แยก PlayerControlView และแก้ไขให้เหมาะกับความต้องการของคุณ

การกำหนดค่าพารามิเตอร์การเล่นสด

ExoPlayer ใช้พารามิเตอร์บางอย่างเพื่อควบคุมออฟเซ็ตของตำแหน่งการเล่น จากขอบสตรีมแบบสด และช่วงความเร็วในการเล่นที่สามารถนำไปใช้เพื่อ ให้ปรับออฟเซ็ตนี้

ExoPlayer จะได้รับค่าของพารามิเตอร์เหล่านี้จาก 3 ตำแหน่งจากมากไปน้อย ลำดับความสำคัญ (ใช้ค่าแรกที่พบ):

  • ตาม MediaItem ค่าที่ส่งไปยัง MediaItem.Builder.setLiveConfiguration
  • ค่าเริ่มต้นส่วนกลางที่ตั้งค่าใน DefaultMediaSourceFactory
  • ค่าจะอ่านจากสื่อโดยตรง

Kotlin

// Global settings.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
    .build()

// Per MediaItem settings.
val mediaItem =
  MediaItem.Builder()
    .setUri(mediaUri)
    .setLiveConfiguration(
      MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()
    )
    .build()
player.setMediaItem(mediaItem)

Java

// Global settings.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
        .build();

// Per MediaItem settings.
MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(mediaUri)
        .setLiveConfiguration(
            new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build())
        .build();
player.setMediaItem(mediaItem);

ค่าของการกำหนดค่าที่ใช้ได้มีดังนี้

  • targetOffsetMs: ออฟเซ็ตแบบเรียลไทม์เป้าหมาย โปรแกรมเล่นจะพยายาม ใกล้กับออฟเซ็ตแบบเรียลไทม์นี้ระหว่างการเล่นหากเป็นไปได้
  • minOffsetMs: ออฟเซ็ตแบบเรียลไทม์ขั้นต่ำที่อนุญาต แม้ในขณะที่กำลังปรับ หักลบกับสภาพเครือข่ายปัจจุบัน โปรแกรมเล่นจะไม่พยายามไปที่ระดับล่าง ของออฟเซ็ตนี้ระหว่างการเล่น
  • maxOffsetMs: ออฟเซ็ตแบบเรียลไทม์สูงสุดที่อนุญาต แม้ในขณะที่กำลังปรับ ชดเชยสภาพเครือข่ายปัจจุบัน โปรแกรมเล่นจะไม่พยายามทำให้อยู่เหนือ ของออฟเซ็ตนี้ระหว่างการเล่น
  • minPlaybackSpeed: ความเร็วขั้นต่ำในการเล่นที่โปรแกรมเล่นใช้ในการย้อนกลับได้ เมื่อพยายามไปให้ถึงออฟเซ็ตแบบสดเป้าหมาย
  • maxPlaybackSpeed: ความเร็วในการเล่นสูงสุดที่โปรแกรมเล่นใช้ติดตามได้ เมื่อพยายามไปให้ถึงออฟเซ็ตแบบสดเป้าหมาย

การปรับความเร็วในการเล่น

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

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

การปรับแต่งอัลกอริทึมการปรับความเร็วในการเล่น

หากเปิดใช้การปรับความเร็ว LivePlaybackSpeedControl จะกำหนดสิ่งต่อไปนี้ ที่มีการปรับค่าใช้จ่าย คุณสามารถใช้ LivePlaybackSpeedControl หรือเพื่อปรับแต่งการใช้งานเริ่มต้น ซึ่งก็คือ DefaultLivePlaybackSpeedControl ในทั้ง 2 กรณี อินสแตนซ์จะตั้งค่าได้เมื่อ การสร้างโปรแกรมเล่น:

Kotlin

val player =
  ExoPlayer.Builder(context)
    .setLivePlaybackSpeedControl(
      DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build()
    )
    .build()

Java

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setLivePlaybackSpeedControl(
            new DefaultLivePlaybackSpeedControl.Builder()
                .setFallbackMaxPlaybackSpeed(1.04f)
                .build())
        .build();

พารามิเตอร์การปรับแต่งที่เกี่ยวข้องของ DefaultLivePlaybackSpeedControl ได้แก่

  • fallbackMinPlaybackSpeed และ fallbackMaxPlaybackSpeed: ค่าต่ำสุดและ ความเร็วในการเล่นสูงสุดที่สามารถใช้ปรับได้หากไม่มีทั้งสื่อ และ MediaItem ที่ได้จากแอปจะเป็นตัวกำหนดขีดจำกัด
  • proportionalControlFactor: ควบคุมความลื่นไหลของการปรับความเร็ว ต ค่าที่สูงจะทำให้การปรับเปลี่ยนนั้นกระทันหันและตอบสนองได้ไวขึ้น และมีแนวโน้มมากขึ้นที่จะ ได้ฟังเสียง ค่าที่น้อยกว่าจะทำให้การเปลี่ยนความเร็วเป็นไปอย่างราบรื่นมากขึ้น แต่ทำงานช้าลง
  • targetLiveOffsetIncrementOnRebufferMs: ระบบจะเพิ่มค่านี้ลงในเป้าหมาย สดใหม่ทุกครั้งที่เกิดการบัฟเฟอร์ซ้ำเพื่อดำเนินการด้วยความระมัดระวังมากขึ้น คุณปิดฟีเจอร์นี้ได้โดยตั้งค่าเป็น 0
  • minPossibleLiveOffsetSmoothingFactor: ปัจจัยการปรับให้เรียบแบบเอ็กซ์โปเนนเชียลที่ จะใช้เพื่อติดตามค่าชดเชยขั้นต่ำที่เป็นไปได้สำหรับปัจจุบัน โดยพิจารณาจาก สื่อที่บัฟเฟอร์ ค่าที่ใกล้ 1 มากหมายความว่าค่าประมาณมีค่ามากกว่า อย่างระมัดระวังและอาจใช้เวลานานขึ้นในการปรับสภาพเครือข่ายให้ดีขึ้น ในขณะที่ ค่าที่ต่ำกว่าหมายความว่าการประมาณการจะปรับเร็วขึ้นและมีความเสี่ยงมากขึ้น เจอการบัฟเฟอร์ซ้ำ

BehindLiveWindowException และ ERROR_CODE_BEHIND_LIVE_WINDOW

ตำแหน่งการเล่นอาจอยู่หลังหน้าต่างถ่ายทอดสด ตัวอย่างเช่น หากโปรแกรมเล่น หยุดชั่วคราวหรือบัฟเฟอร์เป็นระยะเวลานานพอ หากเกิดกรณีเช่นนี้ การเล่นจะล้มเหลวและข้อยกเว้นที่มีรหัสข้อผิดพลาด ERROR_CODE_BEHIND_LIVE_WINDOW จะได้รับการรายงานผ่าน Player.Listener.onPlayerError โค้ดของแอปพลิเคชันอาจต้องจัดการ โดยเล่นต่อที่ตำแหน่งเริ่มต้น กิจกรรมโปรแกรมเล่นของ แอปเดโมยกตัวอย่างวิธีการนี้

Kotlin

override fun onPlayerError(error: PlaybackException) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition()
    player.prepare()
  } else {
    // Handle other errors
  }
}

Java

@Override
public void onPlayerError(PlaybackException error) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition();
    player.prepare();
  } else {
    // Handle other errors
  }
}