ExoPlayer supporta una vasta gamma di esigenze di analisi di riproduzione. Essenzialmente, Analytics riguarda la raccolta, l'interpretazione, l'aggregazione e il riepilogo dei dati dalle riproduzioni. Questi dati possono essere utilizzati sul dispositivo, ad esempio per il logging, il debug o per orientare le future decisioni di riproduzione oppure che vengono segnalati a un per monitorare le riproduzioni su tutti i dispositivi.
In genere un sistema di analisi deve prima raccogliere gli eventi e poi elaborarli per renderle significative:
- Raccolta di eventi:
Per farlo, puoi registrare un
AnalyticsListener
su unExoPlayer
in esecuzione in un'istanza Compute Engine. I listener di dati e analisi registrati ricevono gli eventi man mano che si verificano durante dall'utilizzo del player. Ogni evento è associato ai contenuti multimediali corrispondenti all'elemento musicale della playlist, oltre alla posizione di riproduzione e ai metadati relativi al timestamp. - Elaborazione degli eventi:
Alcuni sistemi di analisi caricano gli eventi non elaborati su un server, con tutti gli eventi
dell'elaborazione lato server. È anche possibile elaborare eventi
dispositivo, il che potrebbe essere più semplice o ridurre la quantità di informazioni
deve essere caricato. ExoPlayer fornisce
PlaybackStatsListener
, che ti consente di eseguire le seguenti fasi di elaborazione:- Interpretazione degli eventi: per essere utili ai fini dell'analisi, gli eventi devono
da interpretare nel contesto di una singola riproduzione. Ad esempio, i file non elaborati
l'evento di un cambio dello stato del player in
STATE_BUFFERING
può corrispondere a buffer iniziale, rebuffer o buffering che si verifica dopo una ricerca. - Monitoraggio dello stato: questo passaggio converte gli eventi in contatori. Ad esempio: gli eventi di modifica dello stato possono essere convertiti in contatori che monitorano il tempo speso in ogni stato di riproduzione. Il risultato è un set base di dati di analisi per una singola riproduzione.
- Aggregazione: questo passaggio combina i dati di analisi di più riproduzioni, tipicamente aggiungendo contatori.
- Calcolo delle metriche di riepilogo. Molte delle metriche più utili sono quelli che calcolano le medie o che combinano i valori dei dati di analisi di base in altri modi. Le metriche di riepilogo possono essere calcolate per una o più metriche riproduzioni.
- Interpretazione degli eventi: per essere utili ai fini dell'analisi, gli eventi devono
da interpretare nel contesto di una singola riproduzione. Ad esempio, i file non elaborati
l'evento di un cambio dello stato del player in
Raccolta eventi con AnalyticsListener
Gli eventi di riproduzione non elaborata del player vengono segnalati a AnalyticsListener
implementazioni. Puoi aggiungere facilmente il tuo listener e sostituire solo il valore
metodi che ti interessano:
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) {} });
Il EventTime
passato a ogni callback associa l'evento a un contenuto multimediale
dell'elemento della playlist, oltre alla posizione di riproduzione e ai metadati relativi al timestamp:
realtimeMs
: l'ora attuale dell'evento.timeline
,windowIndex
emediaPeriodId
: definisce la playlist e i all'interno della playlist a cui appartiene l'evento.mediaPeriodId
contiene informazioni aggiuntive facoltative, ad esempio indica se appartiene a un annuncio all'interno dell'elemento.eventPlaybackPositionMs
: la posizione di riproduzione nell'elemento quando si verifica l'evento si è verificato un errore.currentTimeline
,currentWindowIndex
,currentMediaPeriodId
ecurrentPlaybackPositionMs
: come sopra, ma per l'elemento attualmente in riproduzione. La l'elemento attualmente in riproduzione potrebbe essere diverso dall'elemento a cui l'evento ad esempio se l'evento corrisponde al pre-buffering del l'elemento da riprodurre.
Elaborazione degli eventi con PlaybackStatsListener
PlaybackStatsListener
è un AnalyticsListener
che implementa sul dispositivo
dell'elaborazione degli eventi. Calcola PlaybackStats
, con i contatori e i valori derivati
metriche tra cui:
- Metriche di riepilogo, ad esempio il tempo di riproduzione totale.
- Metriche relative alla qualità della riproduzione adattiva, ad esempio la risoluzione media dei video.
- Metriche relative alla qualità del rendering, ad esempio la frequenza di frame interrotti.
- Metriche di utilizzo delle risorse, ad esempio il numero di byte letti sulla rete.
Troverai un elenco completo dei conteggi disponibili e delle metriche derivate nella
PlaybackStats
Javadoc.
PlaybackStatsListener
calcola un valore di PlaybackStats
separato per ogni elemento multimediale
nella playlist nonché ogni annuncio lato client inserito all'interno di questi elementi. Tu
può inviare un callback a PlaybackStatsListener
per ricevere informazioni sull'attività
riproduzioni e usare il valore EventTime
passato al callback per identificare
riproduzione terminata. È possibile aggregare i dati di analisi per
più riproduzioni. È anche possibile eseguire query su PlaybackStats
per
sessione di riproduzione corrente in qualsiasi momento utilizzando
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. }));
Il costruttore di PlaybackStatsListener
offre la possibilità di mantenere l'intero
degli eventi elaborati. Tieni presente che potrebbe verificarsi un overhead di memoria sconosciuto
a seconda della durata della riproduzione e del numero di eventi. Pertanto,
attivala solo se hai bisogno di accedere alla cronologia completa
piuttosto che ai dati di analisi finali.
Tieni presente che PlaybackStats
utilizza un insieme esteso di stati per indicare non solo
lo stato dei contenuti multimediali, ma anche l'intenzione dell'utente di riprodurli e i dettagli
ad esempio il motivo per cui la riproduzione è stata interrotta o terminata:
Stato di riproduzione | Intenzione dell'utente di giocare | Nessuna intenzione di giocare |
---|---|---|
Prima della riproduzione | JOINING_FOREGROUND |
NOT_STARTED , JOINING_BACKGROUND |
Riproduzione attiva | PLAYING |
|
Riproduzione interrotta | BUFFERING , SEEKING |
PAUSED , PAUSED_BUFFERING , SUPPRESSED , SUPPRESSED_BUFFERING e INTERRUPTED_BY_AD |
Stati di fine | ENDED , STOPPED , FAILED , ABANDONED |
L'intenzione dell'utente di giocare è importante per distinguere i momenti in cui
in attesa attiva della riproduzione per continuare dai tempi di attesa passivi. Ad esempio:
PlaybackStats.getTotalWaitTimeMs
restituisce il tempo totale trascorso nel
JOINING_FOREGROUND
, BUFFERING
e SEEKING
, ma non l'ora in cui
la riproduzione è stata messa in pausa. Analogamente, PlaybackStats.getTotalPlayAndWaitTimeMs
restituisce il tempo totale con l'intenzione di un utente di giocare, ovvero il totale
tempo di attesa e il tempo totale trascorso nello stato PLAYING
.
Eventi elaborati e interpretati
Puoi registrare gli eventi elaborati e interpretati utilizzando PlaybackStatsListener
con keepHistory=true
. L'elemento PlaybackStats
risultante conterrà
seguenti elenchi di eventi:
playbackStateHistory
: un elenco ordinato di stati di riproduzione estesa con ilEventTime
da cui ha iniziato a candidarsi. Puoi anche utilizzarePlaybackStats.getPlaybackStateAtTime
per controllare lo stato in un determinato muro orologio.mediaTimeHistory
: una cronologia delle coppie di tempo reale e media che consente ricostruire quali parti dei contenuti multimediali sono state riprodotte in un determinato momento. Puoi usa anchePlaybackStats.getMediaTimeMsAtRealtimeMs
per cercare media in un determinato orario.videoFormatHistory
eaudioFormatHistory
: elenchi ordinati di video e formati audio utilizzati durante la riproduzione con il dispositivoEventTime
da cui sono partiti da utilizzare.fatalErrorHistory
enonFatalErrorHistory
: elenchi ordinati di elementi irreversibili e errori non irreversibili conEventTime
in cui si sono verificati. Gli errori irreversibili sono quelli che hanno terminato la riproduzione, mentre gli errori non irreversibili potrebbero essere recuperabili.
Dati analitici relativi alla riproduzione singola
Questi dati vengono raccolti automaticamente se utilizzi PlaybackStatsListener
, anche
con keepHistory=false
. I valori finali sono i campi pubblici che puoi
trova nel JavaScript PlaybackStats
e le durate degli stati di riproduzione
restituito da getPlaybackStateDurationMs
. Per praticità, troverai anche
come getTotalPlayTimeMs
e getTotalWaitTimeMs
che restituiscono il valore
durata di combinazioni specifiche di stati di riproduzione.
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);
Aggregare dati analitici relativi a più riproduzioni
Puoi combinare più PlaybackStats
insieme chiamando
PlaybackStats.merge
. Il risultato di PlaybackStats
conterrà i dati aggregati
i dati di tutte le riproduzioni unite. Tieni presente che non conterrà la cronologia di
singoli eventi di riproduzione, poiché non possono essere aggregati.
Puoi usare PlaybackStatsListener.getCombinedPlaybackStats
per ricevere un
una visualizzazione aggregata di tutti i dati analitici raccolti nel corso di un
PlaybackStatsListener
.
Metriche di riepilogo calcolato
Oltre ai dati analitici di base, PlaybackStats
offre molti metodi
per calcolare le metriche di riepilogo.
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());
Argomenti avanzati
Associazione dei dati analitici ai metadati di riproduzione
Quando raccogli dati di analisi per le singole riproduzioni, ti consigliamo di associare i dati di analisi della riproduzione ai metadati relativi ai contenuti multimediali riprodotto.
È consigliabile impostare metadati specifici per i media con MediaItem.Builder.setTag
.
Il tag multimediale fa parte di EventTime
registrato per gli eventi non elaborati e quando
PlaybackStats
sono finiti, quindi possono essere facilmente recuperati durante l'uso di
dati analitici corrispondenti:
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. });
Generare report sugli eventi di analisi personalizzati
Se devi aggiungere eventi personalizzati ai dati di analisi, devi salvare
questi eventi nella tua struttura di dati e combinarli con
PlaybackStats
dopo. Se ti aiuta, puoi estendere DefaultAnalyticsCollector
generare EventTime
istanze per gli eventi personalizzati e inviare
ai listener già registrati, come mostrato nell'esempio seguente.
Kotlin
private interface ExtendedListener : AnalyticsListener { fun onCustomEvent(eventTime: EventTime) } private class ExtendedCollector : DefaultAnalyticsCollector(Clock.DEFAULT) { fun customEvent() { val eventTime = generateCurrentPlayerMediaPeriodEventTime() sendEvent(eventTime, CUSTOM_EVENT_ID) { listener: AnalyticsListener -> if (listener is ExtendedListener) { listener.onCustomEvent(eventTime) } } } } // 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
private interface ExtendedListener extends AnalyticsListener { void onCustomEvent(EventTime eventTime); } 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); } }); } } // 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();