ExoPlayer mendukung berbagai kebutuhan analisis pemutaran. Pada akhirnya, analisis adalah tentang mengumpulkan, menafsirkan, menggabungkan, dan meringkas data dari pemutaran. Data ini dapat digunakan di perangkat—misalnya untuk logging, proses debug, atau untuk menginformasikan keputusan pemutaran di masa mendatang—atau dilaporkan ke server untuk memantau pemutaran di semua perangkat.
Sistem analisis biasanya perlu mengumpulkan peristiwa terlebih dahulu, lalu memprosesnya lebih lanjut agar bermakna:
- Pengumpulan peristiwa:
Hal ini dapat dilakukan dengan mendaftarkan
AnalyticsListenerpada instanceExoPlayer. Pemroses analisis terdaftar menerima peristiwa saat terjadi selama penggunaan pemutar. Setiap peristiwa dikaitkan dengan item media yang sesuai dalam playlist, serta posisi pemutaran dan metadata stempel waktu. - Pemrosesan peristiwa:
Beberapa sistem analisis mengupload peristiwa mentah ke server, dengan semua pemrosesan peristiwa dilakukan di sisi server. Anda juga dapat memproses peristiwa di
perangkat, dan melakukannya mungkin lebih mudah atau mengurangi jumlah informasi yang
perlu diupload. ExoPlayer menyediakan
PlaybackStatsListener, yang memungkinkan Anda melakukan langkah-langkah pemrosesan berikut:- Penafsiran peristiwa: Agar berguna untuk tujuan analisis, peristiwa perlu
ditafsirkan dalam konteks satu pemutaran. Misalnya, peristiwa mentah
perubahan status pemutar ke
STATE_BUFFERINGdapat sesuai dengan buffering awal, buffering ulang, atau buffering yang terjadi setelah pencarian. - Pelacakan status: Langkah ini mengonversi peristiwa menjadi penghitung. Misalnya, peristiwa perubahan status dapat dikonversi menjadi penghitung yang melacak berapa banyak waktu yang dihabiskan di setiap status pemutaran. Hasilnya adalah kumpulan dasar nilai data analisis untuk satu pemutaran.
- Agregasi: Langkah ini menggabungkan data analisis di beberapa pemutaran, biasanya dengan menjumlahkan penghitung.
- Penghitungan metrik ringkasan: Banyak metrik yang paling berguna adalah metrik yang menghitung rata-rata atau menggabungkan nilai data analisis dasar dengan cara lain. Metrik ringkasan dapat dihitung untuk satu atau beberapa pemutaran.
- Penafsiran peristiwa: Agar berguna untuk tujuan analisis, peristiwa perlu
ditafsirkan dalam konteks satu pemutaran. Misalnya, peristiwa mentah
perubahan status pemutar ke
Pengumpulan peristiwa dengan AnalyticsListener
Peristiwa pemutaran mentah dari pemutar dilaporkan ke implementasi AnalyticsListener. Anda dapat menambahkan pemroses Anda sendiri dan hanya mengganti metode yang
Anda minati:
Kotlin
exoPlayer.addAnalyticsListener( object : AnalyticsListener { override fun onPlaybackStateChanged(eventTime: EventTime, @Player.State state: Int) {} override fun onDroppedVideoFrames( eventTime: EventTime, droppedFrames: Int, elapsedMs: Long, ) {} } )
Java
exoPlayer.addAnalyticsListener( new AnalyticsListener() { @Override public void onPlaybackStateChanged(EventTime eventTime, @Player.State int state) {} @Override public void onDroppedVideoFrames( EventTime eventTime, int droppedFrames, long elapsedMs) {} });
EventTime yang diteruskan ke setiap callback mengaitkan peristiwa ke item media
dalam playlist, serta posisi pemutaran dan metadata stempel waktu:
realtimeMs: Waktu jam dinding peristiwa.timeline,windowIndex, danmediaPeriodId: Menentukan playlist dan item dalam playlist yang memiliki peristiwa tersebut.mediaPeriodIdberisi informasi tambahan opsional, misalnya menunjukkan apakah peristiwa tersebut termasuk dalam iklan dalam item.eventPlaybackPositionMs: Posisi pemutaran dalam item saat peristiwa terjadi.currentTimeline,currentWindowIndex,currentMediaPeriodId, dancurrentPlaybackPositionMs: Seperti yang dijelaskan sebelumnya, tetapi untuk item yang sedang diputar. Item yang sedang diputar mungkin berbeda dari item yang terkait dengan peristiwa, misalnya jika peristiwa tersebut sesuai dengan pra-buffering item berikutnya yang akan diputar.
Pemrosesan peristiwa dengan PlaybackStatsListener
PlaybackStatsListener adalah AnalyticsListener yang mengimplementasikan pemrosesan peristiwa di perangkat. Metrik ini menghitung PlaybackStats, dengan penghitung dan metrik turunan, termasuk:
- Metrik ringkasan, misalnya total waktu pemutaran.
- Metrik kualitas pemutaran adaptif, misalnya resolusi video rata-rata.
- Metrik kualitas rendering, misalnya rasio frame yang dilewati.
- Metrik penggunaan resource, misalnya jumlah byte yang dibaca melalui jaringan.
Anda akan menemukan daftar lengkap jumlah yang tersedia dan metrik turunan di
PlaybackStats Javadoc.
PlaybackStatsListener menghitung PlaybackStats terpisah untuk setiap item media
dalam playlist, dan juga setiap iklan sisi klien yang disisipkan dalam item ini. Anda
dapat memberikan callback ke PlaybackStatsListener untuk mendapatkan informasi tentang pemutaran
yang telah selesai, dan menggunakan EventTime yang diteruskan ke callback untuk mengidentifikasi
pemutaran yang telah selesai. Anda dapat menggabungkan data analisis untuk
beberapa pemutaran. Anda juga dapat mengkueri PlaybackStats untuk
sesi pemutaran saat ini kapan saja menggunakan
PlaybackStatsListener.getPlaybackStats().
Kotlin
exoPlayer.addAnalyticsListener( PlaybackStatsListener(/* keepHistory= */ true) { eventTime: EventTime?, playbackStats: PlaybackStats? -> // Analytics data for the session started at `eventTime` is ready. } )
Java
exoPlayer.addAnalyticsListener( new PlaybackStatsListener( /* keepHistory= */ true, (eventTime, playbackStats) -> { // Analytics data for the session started at `eventTime` is ready. }));
Konstruktor PlaybackStatsListener memberikan opsi untuk menyimpan histori lengkap peristiwa yang diproses. Perhatikan bahwa hal ini dapat menimbulkan overhead memori yang tidak diketahui,
bergantung pada durasi pemutaran dan jumlah peristiwa. Oleh karena itu, Anda
hanya boleh mengaktifkannya jika memerlukan akses ke histori lengkap peristiwa yang diproses,
bukan hanya ke data analisis akhir.
Perhatikan bahwa PlaybackStats menggunakan kumpulan status yang diperluas untuk menunjukkan tidak hanya
status media, tetapi juga niat pengguna untuk memutar dan informasi yang lebih mendetail
seperti alasan pemutaran terganggu atau berakhir:
| Status pemutaran | Niat pengguna untuk bermain | Tidak ada niat untuk bermain |
|---|---|---|
| Sebelum pemutaran | JOINING_FOREGROUND |
NOT_STARTED, JOINING_BACKGROUND |
| Pemutaran aktif | PLAYING |
|
| Pemutaran terganggu | BUFFERING, SEEKING |
PAUSED, PAUSED_BUFFERING, SUPPRESSED, SUPPRESSED_BUFFERING, INTERRUPTED_BY_AD |
| Status akhir | ENDED, STOPPED, FAILED, ABANDONED |
Niat pengguna untuk memutar penting untuk membedakan waktu saat pengguna
secara aktif menunggu pemutaran dilanjutkan dari waktu tunggu pasif. Misalnya,
PlaybackStats.getTotalWaitTimeMs menampilkan total waktu yang dihabiskan dalam
status JOINING_FOREGROUND, BUFFERING, dan SEEKING, tetapi bukan waktu saat
pemutaran dijeda. Demikian pula, PlaybackStats.getTotalPlayAndWaitTimeMs akan
menampilkan total waktu dengan niat pengguna untuk bermain, yaitu total waktu tunggu
aktif dan total waktu yang dihabiskan dalam status PLAYING.
Peristiwa yang diproses dan ditafsirkan
Anda dapat mencatat peristiwa yang diproses dan ditafsirkan menggunakan PlaybackStatsListener
dengan keepHistory=true. PlaybackStats yang dihasilkan akan berisi
daftar peristiwa berikut:
playbackStateHistory: Daftar yang diurutkan untuk status pemutaran yang diperpanjang denganEventTimesaat status tersebut mulai diterapkan. Anda juga dapat menggunakanPlaybackStats.getPlaybackStateAtTimeuntuk mencari status pada waktu jam dinding tertentu.mediaTimeHistory: Histori pasangan waktu jam dinding dan waktu media yang memungkinkan Anda merekonstruksi bagian media mana yang diputar pada waktu tertentu. Anda juga dapat menggunakanPlaybackStats.getMediaTimeMsAtRealtimeMsuntuk mencari posisi pemutaran pada waktu jam dinding tertentu.videoFormatHistorydanaudioFormatHistory: Daftar yang diurutkan dari format video dan audio yang digunakan selama pemutaran denganEventTimesaat format tersebut mulai digunakan.fatalErrorHistorydannonFatalErrorHistory: Daftar yang diurutkan dari error fatal dan non-fatal denganEventTimetempat terjadinya. Error fatal adalah error yang mengakhiri pemutaran, sedangkan error non-fatal mungkin dapat dipulihkan.
Data analisis pemutaran tunggal
Data ini dikumpulkan secara otomatis jika Anda menggunakan PlaybackStatsListener, bahkan
dengan keepHistory=false. Nilai akhir adalah kolom publik yang dapat Anda
temukan di PlaybackStats Javadoc dan durasi status pemutaran
yang ditampilkan oleh getPlaybackStateDurationMs. Untuk memudahkan, Anda juga akan menemukan
metode seperti getTotalPlayTimeMs dan getTotalWaitTimeMs yang menampilkan
durasi kombinasi status pemutaran tertentu.
Kotlin
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.totalPlayTimeMs + ", rebuffers = " + playbackStats.totalRebufferCount, )
Java
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.getTotalPlayTimeMs() + ", rebuffers = " + playbackStats.totalRebufferCount);
Menggabungkan data analisis dari beberapa pemutaran
Anda dapat menggabungkan beberapa PlaybackStats dengan memanggil
PlaybackStats.merge. PlaybackStats yang dihasilkan akan berisi data gabungan
dari semua pemutaran yang digabungkan. Perhatikan bahwa laporan ini tidak akan berisi histori peristiwa pemutaran individual, karena peristiwa ini tidak dapat digabungkan.
PlaybackStatsListener.getCombinedPlaybackStats dapat digunakan untuk mendapatkan
tampilan gabungan dari semua data analisis yang dikumpulkan selama masa aktif
PlaybackStatsListener.
Metrik ringkasan yang dihitung
Selain data analisis dasar, PlaybackStats menyediakan banyak metode
untuk menghitung metrik ringkasan.
Kotlin
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.meanVideoFormatBitrate + ", mean time between rebuffers = " + playbackStats.meanTimeBetweenRebuffers, )
Java
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.getMeanVideoFormatBitrate() + ", mean time between rebuffers = " + playbackStats.getMeanTimeBetweenRebuffers());
Topik lanjutan
Mengaitkan data analisis dengan metadata pemutaran
Saat mengumpulkan data analisis untuk setiap pemutaran, Anda mungkin ingin mengaitkan data analisis pemutaran dengan metadata tentang media yang diputar.
Sebaiknya tetapkan metadata khusus media dengan MediaItem.Builder.setTag.
Tag media adalah bagian dari EventTime yang dilaporkan untuk peristiwa mentah dan saat
PlaybackStats selesai, sehingga dapat diambil saat menangani
data analisis yang sesuai:
Kotlin
PlaybackStatsListener(/* keepHistory= */ false) { eventTime: EventTime, playbackStats: PlaybackStats -> val mediaTag = eventTime.timeline .getWindow(eventTime.windowIndex, Timeline.Window()) .mediaItem .localConfiguration ?.tag // Report playbackStats with mediaTag metadata. }
Java
new PlaybackStatsListener( /* keepHistory= */ false, (eventTime, playbackStats) -> { Object mediaTag = eventTime.timeline.getWindow(eventTime.windowIndex, new Timeline.Window()) .mediaItem .localConfiguration .tag; // Report playbackStats with mediaTag metadata. });
Melaporkan peristiwa analisis kustom
Jika Anda perlu menambahkan peristiwa kustom ke data analisis, Anda harus menyimpan
peristiwa ini dalam struktur data Anda sendiri dan menggabungkannya dengan PlaybackStats yang dilaporkan
nanti. Jika perlu, Anda dapat memperluas DefaultAnalyticsCollector
agar dapat membuat instance EventTime untuk peristiwa kustom dan mengirimkannya
ke pemroses yang sudah terdaftar seperti yang ditunjukkan dalam contoh berikut.
Kotlin
@OptIn(UnstableApi::class) private interface ExtendedListener : AnalyticsListener { fun onCustomEvent(eventTime: EventTime) } @OptIn(UnstableApi::class) private class ExtendedCollector : DefaultAnalyticsCollector(Clock.DEFAULT) { fun customEvent() { val eventTime = super.generateCurrentPlayerMediaPeriodEventTime() super.sendEvent(eventTime, CUSTOM_EVENT_ID) { listener: AnalyticsListener -> if (listener is ExtendedListener) { listener.onCustomEvent(eventTime) } } } } @OptIn(UnstableApi::class) fun useExtendedAnalyticsCollector(context: Context) { // Usage - Setup and listener registration. val player = ExoPlayer.Builder(context).setAnalyticsCollector(ExtendedCollector()).build() player.addAnalyticsListener( object : ExtendedListener { override fun onCustomEvent(eventTime: EventTime) { // Save custom event for analytics data. } } ) // Usage - Triggering the custom event. (player.analyticsCollector as ExtendedCollector).customEvent() }
Java
@OptIn(markerClass = UnstableApi.class) private interface ExtendedListener extends AnalyticsListener { void onCustomEvent(EventTime eventTime); } @OptIn(markerClass = UnstableApi.class) private static class ExtendedCollector extends DefaultAnalyticsCollector { public ExtendedCollector() { super(Clock.DEFAULT); } public void customEvent() { AnalyticsListener.EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); sendEvent( eventTime, CUSTOM_EVENT_ID, listener -> { if (listener instanceof ExtendedListener) { ((ExtendedListener) listener).onCustomEvent(eventTime); } }); } } @OptIn(markerClass = UnstableApi.class) public static void useExtendedAnalyticsCollector(Context context) { // Usage - Setup and listener registration. ExoPlayer player = new ExoPlayer.Builder(context).setAnalyticsCollector(new ExtendedCollector()).build(); player.addAnalyticsListener( (ExtendedListener) eventTime -> { // Save custom event for analytics data. }); // Usage - Triggering the custom event. ((ExtendedCollector) player.getAnalyticsCollector()).customEvent(); }
Melacak tombol fitur dan mode Canary
Saat melakukan pengujian A/B atau mengevaluasi dampak pengoptimalan Media3 baru, Anda dapat menghubungkan data analisis pemutaran dengan tombol fitur aktif dan mode Canary.
Anda dapat mengkueri Flags.getLogString atau memeriksa penggantian flag tertentu menggunakan
Flags.getEnabledOverrides dan Flags.getDisabledOverrides untuk menyertakan status
flag dalam payload analisis kustom atau metadata sesi.