Analytics

ExoPlayer, çok çeşitli oynatma analizi ihtiyaçlarını destekler. Sonuç olarak analiz, oynatmalardan gelen verilerin toplanması, yorumlanması, birleştirilmesi ve özetlenmesiyle ilgilidir. Bu veriler cihazda (örneğin günlüğe kaydetme, hata ayıklama veya gelecekteki oynatma kararlarını şekillendirmek amacıyla) kullanılabilir ya da tüm cihazlardaki oynatmaları izlemek için bir sunucuya bildirilebilir.

Analiz sistemlerinin genellikle önce etkinlikleri toplaması ve ardından daha anlamlı hale getirmek için bunları işlemesi gerekir:

  • Etkinlik toplama: Bu işlem, ExoPlayer örneğine bir AnalyticsListener kaydedilerek yapılabilir. Kayıtlı analiz dinleyicileri, oynatıcıyı kullanırken gerçekleşen etkinlikleri alır. Her etkinlik, oynatma konumu ve zaman damgası meta verilerinin yanı sıra oynatma listesindeki ilgili medya öğesiyle ilişkilendirilir.
  • Etkinlik işleme: Bazı analiz sistemleri, ham etkinlikleri bir sunucuya yükler. Tüm etkinlik işlemleri sunucu tarafında gerçekleştirilir. Etkinliklerin cihazda işlenmesi de mümkündür ve bu işlem daha basit olabilir ya da yüklenmesi gereken bilgi miktarını azaltabilir. ExoPlayer, aşağıdaki işleme adımlarını gerçekleştirmenizi sağlayan PlaybackStatsListener özelliğini sunar:
    1. Etkinlik yorumlaması: Analiz açısından faydalı olması için etkinliklerin tek bir oynatma bağlamında yorumlanması gerekir. Örneğin, oyuncu durumunun STATE_BUFFERING olarak değişmesinin ham etkinliği, aramadan sonra gerçekleşen ilk arabelleğe alma, yeniden arabelleğe alma veya arabelleğe alma işlemine karşılık gelebilir.
    2. Durum izleme: Bu adım etkinlikleri sayaçlara dönüştürür. Örneğin, durum değişikliği etkinlikleri, her bir oynatma durumunda ne kadar zaman harcandığını izleyen sayaçlara dönüştürülebilir. Sonuçta, tek bir oynatma için temel bir analiz veri değerleri grubu elde edilir.
    3. Toplama: Bu adım, genellikle sayaçlar toplanarak birden fazla oynatmadaki analiz verilerini birleştirir.
    4. Özet metriklerin hesaplanması: En faydalı metriklerin çoğu, ortalamaları hesaplayan veya temel analiz veri değerlerini başka şekillerde birleştiren metriklerdir. Özet metrikler, bir veya birden fazla oynatma için hesaplanabilir.

AnalyticsListener ile etkinlik toplama

Oynatıcıdan gelen ham oynatma etkinlikleri AnalyticsListener uygulamaya bildirilir. Kendi işleyicinizi kolayca ekleyebilir ve yalnızca ilgilendiğiniz yöntemleri geçersiz kılabilirsiniz:

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

Her geri çağırmaya aktarılan EventTime, etkinliği oynatma listesindeki bir medya öğesinin yanı sıra oynatma konumu ve zaman damgası meta verileriyle ilişkilendirir:

  • realtimeMs: Etkinliğin gerçek saati.
  • timeline, windowIndex ve mediaPeriodId: Oynatma listesini ve oynatma listesinde etkinliğin ait olduğu öğeyi tanımlar. mediaPeriodId, isteğe bağlı ek bilgiler içerir (örneğin, etkinliğin öğedeki bir reklama ait olup olmadığını belirtir).
  • eventPlaybackPositionMs: Etkinlik gerçekleştiğinde öğenin oynatma konumudur.
  • currentTimeline, currentWindowIndex, currentMediaPeriodId ve currentPlaybackPositionMs: Yukarıdaki gibidir ancak şu anda oynatılan öğe için geçerlidir. Şu anda oynatılan öğe, etkinliğin ait olduğu öğeden farklı olabilir. Örneğin, etkinlik, oynatılacak sonraki öğenin önceden arabelleğe alınmasına karşılık geliyorsa.

PlaybackStatsListener ile etkinlik işleme

PlaybackStatsListener, cihaz üzerinde etkinlik işlemeyi uygulayan bir AnalyticsListener'dir. PlaybackStats işlemini, sayaçlar ve aşağıdakiler gibi türetilmiş metriklerle hesaplar:

  • Toplam oynatma süresi gibi özet metrikler.
  • Ortalama video çözünürlüğü gibi uyarlanabilir oynatma kalitesi metrikleri.
  • Atlanan karelerin hızı gibi kalite metrikleri oluşturma.
  • Ağda okunan bayt sayısı gibi kaynak kullanım metrikleri.

Kullanılabilir sayıların ve türetilen metriklerin tam listesini PlaybackStats Javadoc'ta bulabilirsiniz.

PlaybackStatsListener, oynatma listesindeki her bir medya öğesi ve bu öğelere eklenen her bir istemci tarafı reklam için ayrı PlaybackStats hesaplar. Sona eren oynatmalar hakkında bilgi almak için PlaybackStatsListener için bir geri çağırma sağlayabilir ve hangi oynatmanın sona erdiğini belirlemek için geri çağırmaya iletilen EventTime parametresini kullanabilirsiniz. Birden çok oynatma için analiz verileri toplanabilir. Ayrıca, PlaybackStatsListener.getPlaybackStats() kullanarak dilediğiniz zaman mevcut oynatma oturumu için PlaybackStats sorgusunu sorgulayabilirsiniz.

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

PlaybackStatsListener oluşturucusu, işlenen etkinliklerin tüm geçmişini saklama seçeneği sunar. Bu işlemin, oynatmanın uzunluğuna ve etkinlik sayısına bağlı olarak bilinmeyen bir bellek ek yüküne neden olabileceğini unutmayın. Bu nedenle, yalnızca nihai analiz verilerine değil, yalnızca işlenen etkinliklerin tüm geçmişine erişmeniz gerektiğinde bu özelliği etkinleştirmeniz gerekir.

PlaybackStats cihazının yalnızca medyanın durumunu değil, aynı zamanda kullanıcının oynatma niyetini ve oynatmanın neden kesintiye uğradığı ya da sonlandırıldığı gibi daha ayrıntılı bilgileri belirtmek için genişletilmiş bir durum grubu kullandığını unutmayın:

Oynatma durumu Kullanıcı oynamak istiyor Oynamak istemiyorum
Oynatmadan önce JOINING_FOREGROUND NOT_STARTED, JOINING_BACKGROUND
Etkin oynatma PLAYING
Oynatma kesintiye uğradı BUFFERING, SEEKING PAUSED, PAUSED_BUFFERING, SUPPRESSED, SUPPRESSED_BUFFERING, INTERRUPTED_BY_AD
Bitiş eyaletleri ENDED, STOPPED, FAILED, ABANDONED

Kullanıcının oynatma niyetinde olduğu anlar, etkin bir şekilde oynatmanın devam etmesini beklediği zamanları pasif bekleme sürelerinden ayırt etmek için önemlidir. Örneğin PlaybackStats.getTotalWaitTimeMs, JOINING_FOREGROUND, BUFFERING ve SEEKING durumlarında harcanan toplam süreyi döndürür, ancak oynatmanın duraklatıldığı zamanı döndürmez. Benzer şekilde PlaybackStats.getTotalPlayAndWaitTimeMs, kullanıcının oyun oynama niyetine sahip toplam süreyi, yani toplam etkin bekleme süresini ve PLAYING durumunda harcanan toplam süreyi döndürür.

İşlenen ve yorumlanan etkinlikler

keepHistory=true ile PlaybackStatsListener kullanarak işlenen ve yorumlanan etkinlikleri kaydedebilirsiniz. Sonuçta elde edilen PlaybackStats aşağıdaki etkinlik listelerini içerir:

  • playbackStateHistory: Uygulanmaya başlandığı EventTime ile birlikte genişletilmiş oynatma durumlarının sıralı listesi. Belirli bir gerçek saatteki durumu aramak için PlaybackStats.getPlaybackStateAtTime özelliğini de kullanabilirsiniz.
  • mediaTimeHistory: Medyanın hangi bölümlerinin hangi zamanda oynatıldığını yeniden oluşturmanıza olanak tanıyan gerçek zamanlı saat ve medya zaman çiftleri geçmişi. Belirli bir gerçek zamandaki oynatma konumunu bulmak için PlaybackStats.getMediaTimeMsAtRealtimeMs öğesini de kullanabilirsiniz.
  • videoFormatHistory ve audioFormatHistory: Kullanıma sunuldukları EventTime ile oynatma sırasında kullanılan video ve ses biçimlerinin sıralı listeleri.
  • fatalErrorHistory ve nonFatalErrorHistory: Önemli ve önemli olmayan hataların, meydana geldikleri EventTime ile sıralanmış listeleri. Önemli hatalar, oynatmanın sonlandırılmasına yol açan hatalardır. Öte yandan, önemli olmayan hatalar kurtarılabilir.

Tek oynatmalık analiz verileri

Bu veriler, keepHistory=false ile bile PlaybackStatsListener kullanıyorsanız otomatik olarak toplanır. Son değerler, PlaybackStats Javadoc'ta bulabileceğiniz herkese açık alanlar ve getPlaybackStateDurationMs tarafından döndürülen oynatma durumu süreleridir. Size kolaylık sağlaması için belirli oynatma durumu kombinasyonlarının süresini döndüren getTotalPlayTimeMs ve getTotalWaitTimeMs gibi yöntemler de bulabilirsiniz.

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

Birden fazla oynatmanın analiz verilerini birleştirme

PlaybackStats.merge yöntemini çağırarak birden fazla PlaybackStats öğesini birleştirebilirsiniz. Sonuçta elde edilen PlaybackStats, birleştirilen tüm oynatmaların toplu verilerini içerir. Oynatma etkinliklerinin tek tek geçmişini içermeyeceğini unutmayın. Bunlar birleştirilemez.

PlaybackStatsListener.getCombinedPlaybackStats, bir PlaybackStatsListener kullanım ömrü boyunca toplanan tüm analiz verilerinin toplu görünümünü elde etmek için kullanılabilir.

Hesaplanmış özet metrikleri

PlaybackStats, özet metriklerini hesaplamak için temel analiz verilerine ek olarak birçok yöntem sunar.

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

İleri düzey konular

Analiz verilerini oynatma meta verileriyle ilişkilendirme

Ayrı ayrı oynatmalar için analiz verilerini toplarken oynatma analiz verilerini, oynatılan medyayla ilgili meta verilerle ilişkilendirmek isteyebilirsiniz.

Medyaya özel meta verileri MediaItem.Builder.setTag ile ayarlamanız önerilir. Medya etiketi, ham etkinlikler için bildirilen ve PlaybackStats tamamlandığında bildirilen EventTime kapsamında yer alır. Bu sayede, ilgili analiz verileri işlenirken kolayca alınabilir:

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

Özel analiz etkinliklerini raporlama

Analiz verilerine özel etkinlikler eklemeniz gerekirse bu etkinlikleri kendi veri yapınıza kaydetmeniz ve daha sonra raporlanan PlaybackStats etkinliğiyle birleştirmeniz gerekir. İşe yararsa özel etkinlikleriniz için EventTime örnekleri oluşturabilmek ve bunları aşağıdaki örnekte gösterildiği gibi önceden kayıtlı işleyicilere göndermek amacıyla DefaultAnalyticsCollector kapsamını genişletebilirsiniz.

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