Live streaming

ExoPlayer memutar sebagian besar live stream adaptif secara langsung tanpa konfigurasi khusus. Lihat halaman Format yang Didukung untuk detail selengkapnya.

Live stream adaptif menawarkan periode media yang tersedia yang diperbarui dalam interval reguler untuk bergerak sesuai dengan waktu nyata saat ini. Artinya, posisi pemutaran akan selalu berada di suatu tempat dalam periode ini, dalam sebagian besar kasus, dekat dengan real-time saat ini saat streaming diproduksi. Perbedaan antara real-time saat ini dan posisi pemutaran disebut offset live.

Mendeteksi dan memantau pemutaran live

Setiap kali jendela live diperbarui, instance Player.Listener yang terdaftar akan menerima peristiwa onTimelineChanged. Anda dapat mengambil detail tentang pemutaran live saat ini dengan membuat kueri berbagai metode Player dan Timeline.Window, seperti yang tercantum di bawah dan ditampilkan dalam gambar berikut.

Jendela live

  • Player.isCurrentWindowLive menunjukkan apakah item media yang sedang diputar adalah live stream. Nilai ini tetap benar meskipun live stream telah berakhir.
  • Player.isCurrentWindowDynamic menunjukkan apakah item media yang sedang diputar masih diperbarui. Hal ini biasanya berlaku untuk live stream yang belum berakhir. Perhatikan bahwa flag ini juga berlaku untuk non-live stream dalam beberapa kasus.
  • Player.getCurrentLiveOffset menampilkan offset antara waktu real saat ini dan posisi pemutaran (jika tersedia).
  • Player.getDuration menampilkan durasi jendela live saat ini.
  • Player.getCurrentPosition menampilkan posisi pemutaran relatif terhadap awal jendela live.
  • Player.getCurrentMediaItem menampilkan item media saat ini, dengan MediaItem.liveConfiguration berisi penggantian yang disediakan aplikasi untuk parameter offset live target dan penyesuaian offset live.
  • Player.getCurrentTimeline menampilkan struktur media saat ini dalam Timeline. Timeline.Window saat ini dapat diambil dari Timeline menggunakan Player.getCurrentMediaItemIndex dan Timeline.getWindow. Dalam Window:
    • Window.liveConfiguration berisi parameter offset live target dan penyesuaian offset live. Nilai ini didasarkan pada informasi dalam media dan penggantian yang disediakan aplikasi yang ditetapkan di MediaItem.liveConfiguration.
    • Window.windowStartTimeMs adalah waktu sejak Epoch Unix saat jendela live dimulai.
    • Window.getCurrentUnixTimeMs adalah waktu sejak Epoch Unix dari real-time saat ini. Nilai ini dapat diperbaiki oleh perbedaan jam yang diketahui antara server dan klien.
    • Window.getDefaultPositionMs adalah posisi di jendela live tempat pemutar akan memulai pemutaran secara default.

Mencari di live stream

Anda dapat mencari ke mana saja dalam jendela live menggunakan Player.seekTo. Posisi pencarian yang diteruskan bersifat relatif terhadap awal jendela live. Misalnya, seekTo(0) akan mencari ke awal periode live. Pemutar akan mencoba menjaga offset live yang sama dengan posisi yang dicari setelah pencarian.

Jendela live juga memiliki posisi default tempat pemutaran seharusnya dimulai. Posisi ini biasanya berada di dekat tepi aktif. Anda dapat mencari ke posisi default dengan memanggil Player.seekToDefaultPosition.

UI pemutaran live

Komponen UI default ExoPlayer menampilkan durasi jendela live dan posisi pemutaran saat ini di dalamnya. Artinya, posisi akan tampak mundur setiap kali jendela live diperbarui. Jika memerlukan perilaku yang berbeda, misalnya menampilkan waktu Unix atau offset live saat ini, Anda dapat mem-fork PlayerControlView dan mengubahnya sesuai kebutuhan.

Mengonfigurasi parameter pemutaran live

ExoPlayer menggunakan beberapa parameter untuk mengontrol offset posisi pemutaran dari edge live, dan rentang kecepatan pemutaran yang dapat digunakan untuk menyesuaikan offset ini.

ExoPlayer mendapatkan nilai untuk parameter ini dari tiga tempat, dalam urutan prioritas menurun (nilai pertama yang ditemukan akan digunakan):

  • Per nilai MediaItem yang diteruskan ke MediaItem.Builder.setLiveConfiguration.
  • Nilai default global yang ditetapkan di DefaultMediaSourceFactory.
  • Nilai dibaca langsung dari media.

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);

Nilai konfigurasi yang tersedia adalah:

  • targetOffsetMs: Offset live target. Pemutar akan mencoba mendekati offset live ini selama pemutaran jika memungkinkan.
  • minOffsetMs: Offset live minimum yang diizinkan. Meskipun menyesuaikan offset dengan kondisi jaringan saat ini, pemutar tidak akan mencoba berada di bawah offset ini selama pemutaran.
  • maxOffsetMs: Offset live maksimum yang diizinkan. Meskipun menyesuaikan offset dengan kondisi jaringan saat ini, pemutar tidak akan mencoba mendapatkan di atas offset ini selama pemutaran.
  • minPlaybackSpeed: Kecepatan pemutaran minimum yang dapat digunakan pemutar untuk kembali saat mencoba mencapai offset live target.
  • maxPlaybackSpeed: Kecepatan pemutaran maksimum yang dapat digunakan pemutar untuk mengejar saat mencoba mencapai offset live target.

Penyesuaian kecepatan pemutaran

Saat memutar live stream dengan latensi rendah, ExoPlayer akan menyesuaikan offset live dengan mengubah kecepatan pemutaran sedikit. Pemutar akan mencoba mencocokkan offset live target yang disediakan oleh media atau aplikasi, tetapi juga akan mencoba bereaksi terhadap perubahan kondisi jaringan. Misalnya, jika buffering ulang terjadi selama pemutaran, pemutar akan sedikit memperlambat pemutaran untuk menjauh dari tepi live. Jika jaringan kemudian menjadi cukup stabil untuk mendukung pemutaran yang lebih dekat dengan edge live lagi, pemutar akan mempercepat pemutaran untuk kembali ke offset live target.

Jika tidak diinginkan, penyesuaian kecepatan pemutaran otomatis dapat dinonaktifkan dengan menetapkan properti minPlaybackSpeed dan maxPlaybackSpeed ke 1.0f. Demikian pula, fitur ini dapat diaktifkan untuk live stream dengan latensi non-rendah dengan menetapkannya secara eksplisit ke nilai selain 1.0f. Lihat bagian konfigurasi di atas untuk mengetahui detail selengkapnya tentang cara menetapkan properti ini.

Menyesuaikan algoritma penyesuaian kecepatan pemutaran

Jika penyesuaian kecepatan diaktifkan, LivePlaybackSpeedControl akan menentukan penyesuaian yang dilakukan. Anda dapat mengimplementasikan LivePlaybackSpeedControl kustom, atau menyesuaikan implementasi default, yaitu DefaultLivePlaybackSpeedControl. Dalam kedua kasus tersebut, instance dapat ditetapkan saat mem-build pemutar:

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();

Parameter penyesuaian DefaultLivePlaybackSpeedControl yang relevan adalah:

  • fallbackMinPlaybackSpeed dan fallbackMaxPlaybackSpeed: Kecepatan pemutaran minimum dan maksimum yang dapat digunakan untuk penyesuaian jika media atau MediaItem yang disediakan aplikasi tidak menentukan batas.
  • proportionalControlFactor: Mengontrol seberapa lancar penyesuaian kecepatan. Nilai yang tinggi membuat penyesuaian lebih tiba-tiba dan reaktif, tetapi juga lebih mungkin terdengar. Nilai yang lebih kecil akan menghasilkan transisi yang lebih lancar di antara kecepatan, dengan mengorbankan kecepatan yang lebih lambat.
  • targetLiveOffsetIncrementOnRebufferMs: Nilai ini ditambahkan ke offset live target setiap kali buffering ulang terjadi, untuk melanjutkan dengan lebih hati-hati. Fitur ini dapat dinonaktifkan dengan menyetel nilai ke 0.
  • minPossibleLiveOffsetSmoothingFactor: Faktor penghalusan eksponensial yang digunakan untuk melacak offset live minimum yang mungkin berdasarkan media yang saat ini di-buffer. Nilai yang sangat mendekati 1 berarti estimasi lebih hati-hati dan mungkin memerlukan waktu lebih lama untuk menyesuaikan dengan kondisi jaringan yang lebih baik, sedangkan nilai yang lebih rendah berarti estimasi akan menyesuaikan lebih cepat dengan risiko yang lebih tinggi untuk mengalami buffering ulang.

di belakangLiveWindowException dan ERROR_CODE_Fire_LIVE_WINDOW

Posisi pemutaran dapat berada di belakang jendela live, misalnya jika pemutar dijeda atau buffering selama jangka waktu yang cukup lama. Jika hal ini terjadi, pemutaran akan gagal dan pengecualian dengan kode error ERROR_CODE_BEHIND_LIVE_WINDOW akan dilaporkan melalui Player.Listener.onPlayerError. Kode aplikasi mungkin ingin menangani error tersebut dengan melanjutkan pemutaran di posisi default. PlayerActivity aplikasi demo menunjukkan pendekatan ini.

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
  }
}