Analytics

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 un ExoPlayer 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:
    1. 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.
    2. 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.
    3. Aggregazione: questo passaggio combina i dati di analisi di più riproduzioni, tipicamente aggiungendo contatori.
    4. 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.

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 e mediaPeriodId: 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 e currentPlaybackPositionMs: 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 il EventTime da cui ha iniziato a candidarsi. Puoi anche utilizzare PlaybackStats.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 anche PlaybackStats.getMediaTimeMsAtRealtimeMs per cercare media in un determinato orario.
  • videoFormatHistory e audioFormatHistory: elenchi ordinati di video e formati audio utilizzati durante la riproduzione con il dispositivo EventTime da cui sono partiti da utilizzare.
  • fatalErrorHistory e nonFatalErrorHistory: elenchi ordinati di elementi irreversibili e errori non irreversibili con EventTime 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();