Berita Produk
Meningkatkan pemutaran media: Memperkenalkan pramuat dengan Media3 - Bagian 1
Waktu baca: 8 menit
Di aplikasi yang berpusat pada media saat ini, memberikan pengalaman pemutaran yang lancar dan tanpa gangguan adalah kunci untuk pengalaman pengguna yang menyenangkan. Pengguna berharap video mereka dimulai secara instan dan diputar dengan lancar tanpa jeda.
Tantangan utamanya adalah latensi. Biasanya, pemutar video hanya memulai pekerjaannya—menghubungkan, mendownload, mengurai, mem-buffer—setelah pengguna memilih item untuk diputar. Pendekatan reaktif ini lambat untuk konteks video pendek saat ini. Solusinya adalah bersikap proaktif. Kita perlu mengantisipasi video yang akan ditonton pengguna berikutnya dan menyiapkan kontennya terlebih dahulu. Inilah inti dari pramuat.
Manfaat utama pramuat meliputi:
- 🚀 Mulai Pemutaran Lebih Cepat: Video sudah siap diputar, sehingga transisi antar-item lebih cepat dan pemutaran dimulai lebih cepat.
- 📉 Pengurangan Buffering: Dengan memuat data secara proaktif, pemutaran jauh lebih kecil kemungkinannya untuk terhenti, misalnya karena gangguan jaringan.
- ✨ Pengalaman Pengguna yang Lebih Lancar: Kombinasi antara pemutaran yang lebih cepat dan buffering yang lebih sedikit menciptakan interaksi yang lebih lancar dan tanpa gangguan bagi pengguna.
Dalam seri tiga bagian ini, kami akan memperkenalkan dan membahas secara mendalam utilitas Media3 yang canggih untuk memuat komponen (pra).
- Di Bagian 1, kita akan membahas dasar-dasarnya: memahami berbagai strategi pramuat yang tersedia di Media3, mengaktifkan PreloadConfiguration, dan menyiapkan DefaultPreloadManager, sehingga aplikasi Anda dapat memuat item terlebih dahulu. Pada akhir blog ini, Anda akan dapat memuat dan memutar item media terlebih dahulu dengan peringkat dan durasi yang telah dikonfigurasi.
- Di Bagian 2, kita akan membahas topik DefaultPreloadManager yang lebih mendalam: menggunakan pemroses untuk analisis, mempelajari praktik terbaik yang siap produksi seperti pola jendela geser dan komponen bersama kustom DefaultPreloadManager dan ExoPlayer.
- Di Bagian 3, kita akan membahas secara mendalam caching disk dengan DefaultPreloadManager.
Pramuat dapat menolong! 🦸♀️
Ide utama di balik pramuat sangat sederhana: muat konten media sebelum Anda membutuhkannya. Saat pengguna menggeser ke video berikutnya, segmen pertama video sudah didownload dan tersedia, siap untuk diputar segera.
Bayangkan seperti restoran. Dapur yang sibuk tidak menunggu pesanan untuk mulai memotong bawang. 🧅 Mereka melakukan pekerjaan persiapan terlebih dahulu. Pramuat adalah pekerjaan persiapan untuk pemutar video Anda.
Jika diaktifkan, pramuat dapat membantu meminimalkan latensi gabungan saat pengguna melompat ke item berikutnya sebelum buffer pemutaran mencapai item berikutnya. Periode pertama jendela berikutnya disiapkan dan sampel video, audio, dan teks di-buffer. Periode yang dimuat terlebih dahulu kemudian dimasukkan ke dalam antrean pemutar dengan sampel yang di-buffer segera tersedia dan siap untuk dimasukkan ke codec untuk rendering.
Di Media3, ada dua API utama untuk pramuat, yang masing-masing cocok untuk kasus penggunaan yang berbeda. Memilih API yang tepat adalah langkah pertama.
1. Memuat item playlist terlebih dahulu dengan PreloadConfiguration
Ini adalah pendekatan sederhana, berguna untuk media linear dan berurutan seperti playlist yang urutan pemutarannya dapat diprediksi (seperti serangkaian episode). Anda memberikan daftar lengkap item media kepada pemutar menggunakan API playlist ExoPlayer dan menetapkan PreloadConfiguration untuk pemutar, lalu pemutar akan otomatis memuat item berikutnya dalam urutan seperti yang dikonfigurasi. API ini mencoba mengoptimalkan latensi gabungan saat pengguna melompat ke item berikutnya sebelum buffer pemutaran sudah tumpang-tindih ke item berikutnya.
Pramuat hanya dimulai saat tidak ada media yang dimuat untuk pemutaran yang sedang berlangsung, sehingga mencegahnya bersaing untuk bandwidth dengan pemutaran utama.
Jika Anda masih tidak yakin apakah memerlukan pramuat, API ini adalah opsi yang mudah untuk dicoba.
player.preloadConfiguration =
PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)
Dengan PreloadConfiguration di atas, pemutar mencoba memuat media selama lima detik untuk item berikutnya dalam playlist.
Setelah ikut serta, pramuat playlist dapat dinonaktifkan lagi menggunakan PreloadConfiguration.DEFAULT untuk menonaktifkan pramuat playlist:
player.preloadConfiguration = PreloadConfiguration.DEFAULT
2. Memuat daftar dinamis terlebih dahulu dengan PreloadManager
Untuk UI dinamis seperti feed vertikal atau carousel, tempat item "berikutnya" ditentukan oleh interaksi pengguna, PreloadManager API cocok digunakan. Ini adalah komponen baru yang canggih dan mandiri dalam library Media3 ExoPlayer yang dirancang khusus untuk memuat terlebih dahulu secara proaktif. Komponen ini mengelola kumpulan MediaSource potensial, memprioritaskannya berdasarkan kedekatan dengan posisi pengguna saat ini dan menawarkan kontrol terperinci atas item yang akan dimuat terlebih dahulu, cocok untuk skenario kompleks seperti feed dinamis video pendek.
Menyiapkan PreloadManager
DefaultPreloadManager adalah implementasi kanonis untuk PreloadManager.
Builder DefaultPreloadManager dapat membuat DefaultPreloadManager dan instance ExoPlayer yang akan memutar konten yang dimuat terlebih dahulu. Untuk membuat DefaultPreloadManager, Anda harus meneruskan TargetPreloadStatusControl, yang dapat dikueri oleh pengelola pramuat untuk mengetahui jumlah item yang akan dimuat. Kami akan menjelaskan dan menentukan contoh TargetPreloadStatusControl di bagian bawah.
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl) val preloadManager = val preloadManagerBuilder.build() // Build ExoPlayer with DefaultPreloadManager.Builder val player = preloadManagerBuilder.buildExoPlayer()
Menggunakan builder yang sama untuk ExoPlayer dan DefaultPreloadManager diperlukan, yang memastikan bahwa komponen di dalamnya dibagikan dengan benar.
Selesai. Anda kini memiliki pengelola yang siap menerima petunjuk.
Mengonfigurasi Durasi dan Peringkat dengan TargetPreloadStatusControl
Bagaimana jika Anda ingin memuat video selama 10 detik terlebih dahulu? Anda dapat memberikan posisi item media di carousel, dan DefaultPreloadManager memprioritaskan pemuatan item berdasarkan seberapa dekat item tersebut dengan item yang saat ini diputar pengguna.
Jika ingin mengontrol durasi item yang akan dimuat terlebih dahulu, Anda dapat melakukannya dengan DefaultPreloadManager.PreloadStatus yang ditampilkan.
Misalnya,
- Item 'A' adalah prioritas tertinggi, muat video selama 5 detik terlebih dahulu.
- Item 'B' adalah prioritas sedang, tetapi saat Anda sampai ke item tersebut, muat video selama 3 detik terlebih dahulu.
- Item 'C' memiliki prioritas lebih rendah, muat hanya trek.
- Item 'D' memiliki prioritas yang lebih rendah, cukup siapkan.
- Item lainnya jauh, Jangan muat apa pun terlebih dahulu.
Kontrol terperinci ini dapat membantu Anda mengoptimalkan penggunaan resource yang direkomendasikan untuk pemutaran yang lancar.
import androidx.media3.exoplayer.DefaultPreloadManager.PreloadStatus
class MyTargetPreloadStatusControl(
currentPlayingIndex: Int = C.INDEX_UNSET
) : TargetPreloadStatusControl<Int,PreloadStatus> {
// The app is responsible for updating this based on UI state
override fun getTargetPreloadStatus(index: Int): PreloadStatus? {
val distance = index - currentPlayingIndex
// Adjacent items (Next): preload 5 seconds
if (distance == 1) {
// Return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and suggest loading // 5000ms from the default start position
return PreloadStatus.specifiedRangeLoaded(5000L)
}
// Adjacent items (Previous): preload 3 seconds
else if (distance == -1) {
// Return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED //and suggest loading 3000ms from the default start position
return PreloadStatus.specifiedRangeLoaded(3000L)
}
// Items two positions away: just select tracks
else if (distance) == 2) {
// Return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
return PreloadStatus.TRACKS_SELECTED
}
// Items four positions away: just select prepare
else if (abs(distance) <= 4) {
// Return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
return PreloadStatus.SOURCE_PREPARED
}
// All other items are too far away
return null
}
}
Tips: PreloadManager dapat memuat item sebelumnya dan berikutnya terlebih dahulu, sedangkan PreloadConfiguration hanya akan melihat item berikutnya.
Mengelola Item Pramuat
Setelah pengelola dibuat, Anda dapat mulai memberi tahu item yang akan dikerjakan. Saat pengguna men-scroll feed, Anda akan mengidentifikasi video mendatang dan menambahkannya ke pengelola. Interaksi dengan PreloadManager adalah percakapan berbasis status antara UI dan mesin pramuat.
1. Menambahkan Item Media
Saat mengisi feed, Anda harus memberi tahu pengelola tentang media yang perlu dilacak. Jika baru memulai, Anda dapat menambahkan seluruh daftar yang ingin dimuat terlebih dahulu. Selanjutnya, Anda dapat terus menambahkan satu item ke daftar sesuai kebutuhan. Anda memiliki kontrol penuh atas item yang ada dalam daftar pramuat, yang berarti Anda juga harus mengelola item yang ditambahkan dan dihapus dari pengelola.
val initialMediaItems = pullMediaItemsFromService(/* count= */ 20)
for (index in 0 until initialMediaItems.size) {
preloadManager.add(
initialMediaItems.get(index),index)
)
}
Pengelola kini akan mulai mengambil data untuk MediaItem ini di latar belakang.
Setelah menambahkan, beri tahu pengelola untuk mengevaluasi ulang daftar barunya (menunjukkan bahwa ada sesuatu yang telah berubah seperti menambahkan/ menghapus item, atau pengguna beralih untuk memutar item baru).
preloadManager.invalidate()
2. Mengambil dan Memutar Item
Berikut logika pemutaran utama. Saat pengguna memutuskan untuk memutar video tersebut, Anda tidak perlu membuat MediaSource baru. Sebagai gantinya, Anda meminta PreloadManager untuk item yang telah disiapkannya. Anda dapat mengambil MediaSource dari Pengelola Pramuat menggunakan MediaItem.
Jika item yang diambil dari PreloadManager adalah null, berarti mediaItem belum dimuat terlebih dahulu atau ditambahkan ke PreloadMamager, sehingga Anda memilih untuk menetapkan mediaItem secara langsung.
// When a media item is about to display on the screen
val mediaSource = preloadManager.getMediaSource(mediaItem)
if (mediaSource!= null) {
player.setMediaSource(mediaSource)
} else {
// If mediaSource is null, that mediaItem hasn't been added yet.
// So, send it directly to the player.
player.setMediaItem(mediaItem)
}
player.prepare()
// When the media item is displaying at the center of the screen
player.play()
Dengan menyiapkan MediaSource yang diambil dari PreloadManager, Anda akan bertransisi dengan lancar dari pramuat ke pemutaran, menggunakan data yang sudah ada dalam memori. Hal inilah yang membuat waktu mulai lebih cepat.
3. Menjaga indeks saat ini tetap sinkron dengan UI
Karena feed / daftar kita dapat bersifat dinamis, penting untuk memberi tahu PreloadManager tentang indeks pemutaran saat ini sehingga pengelola dapat selalu memprioritaskan item yang paling dekat dengan indeks saat ini untuk pramuat.
preloadManager.setCurrentPlayingIndex(currentIndex) // Need to call invalidate() to update the priorities preloadManager.invalidate()
4. Menghapus Item
Agar pengelola tetap efisien, Anda harus menghapus item yang tidak perlu lagi dilacak, seperti item yang jauh dari posisi pengguna saat ini.
// When an item is too far from the current playing index preloadManager.remove(mediaItem)
Jika perlu menghapus semua item sekaligus, Anda dapat memanggil preloadManager.reset().
5. Merilis Pengelola
Jika tidak lagi memerlukan PreloadManager (misalnya, saat UI dihancurkan), Anda harus merilisnya untuk mengosongkan resource-nya. Tempat yang baik untuk melakukannya adalah tempat Anda sudah merilis resource Pemutar. Sebaiknya rilis pengelola sebelum pemutar karena pemutar dapat terus diputar jika Anda tidak memerlukan pramuat lagi.
// In your Activity's onDestroy() or Composable's onDispose preloadManager.release()
Waktu demo
Lihat langsung cara kerjanya 👍
Dalam demo di bawah , kita melihat dampak PreloadManager di sisi kanan yang memiliki waktu pemuatan lebih cepat, sedangkan sisi kiri menunjukkan pengalaman yang ada. Anda juga dapat melihat contoh kode sample untuk demo. (Bonus: Kode ini juga menampilkan latensi startup untuk setiap video)
Apa Langkah Selanjutnya?
Selesai untuk Bagian 1. Anda kini memiliki alat untuk membuat sistem pramuat dinamis. Anda dapat menggunakan PreloadConfiguration untuk memuat item playlist berikutnya terlebih dahulu di ExoPlayer atau menyiapkan DefaultPreloadManager, menambahkan dan menghapus item dengan cepat, mengonfigurasi status pramuat target, dan mengambil konten yang dimuat terlebih dahulu dengan benar untuk pemutaran.
Di Bagian 2, kita akan membahas DefaultPreloadManager lebih mendalam. Kita akan mempelajari cara memproses peristiwa pramuat, membahas praktik terbaik seperti menggunakan jendela geser untuk menghindari masalah memori, dan melihat komponen bersama kustom ExoPlayer dan DefaultPreloadManager.
Apakah Anda memiliki masukan untuk dibagikan? Kami ingin mendengar masukan dari Anda.
Tetap ikuti perkembangan, dan buat aplikasi Anda lebih cepat. 🚀
Lanjutkan membaca
-
Berita Produk
Selamat datang di bagian kedua dari seri tiga bagian kami tentang pramuat media dengan Media3. Seri ini dirancang untuk memandu Anda melalui proses pembuatan pengalaman media yang sangat responsif dan latensi rendah di aplikasi Android.
Mayuri Khinvasara Khabya • Waktu baca: 9 menit
-
Berita Produk
Di Google I/O tahun ini, kami membahas model bisnis kami yang terus berkembang dan menawarkan lebih banyak pilihan serta cara baru agar aplikasi dan konten Anda dapat ditemukan di dalam dan di luar Play Store. Kami juga memperkenalkan alat dan insight canggih yang akan membantu menskalakan bisnis Anda dengan lebih mudah.
Paul Feng • Waktu baca: 6 menit
-
Berita Produk
Dengan senang hati kami mengumumkan bahwa dukungan resmi untuk Unreal Engine dan Godot telah hadir untuk Android XR. Kami juga meluncurkan alat baru yang dirancang untuk meningkatkan produktivitas Anda dan mengaktifkan kemampuan XR baru: Android XR Engine Hub dan Android XR Interaction Framework.
Luke Hopkins • Waktu baca: 4 menit
Terus dapatkan informasi
Dapatkan insight pengembangan Android terbaru yang dikirim ke kotak masuk Anda setiap minggu.