Analytics

ExoPlayer, वीडियो चलाने से जुड़े आंकड़े इकट्ठा करने की कई ज़रूरतों को पूरा करता है. आखिर में, आंकड़ों का मतलब वीडियो चलाने से जुड़ा डेटा इकट्ठा करना, उसका विश्लेषण करना, उसे इकट्ठा करना, और खास जानकारी के तौर पर दिखाना है. इस डेटा का इस्तेमाल, डिवाइस पर किया जा सकता है. उदाहरण के लिए, लॉग करने, डीबग करने या आने वाले समय में वीडियो चलाने से जुड़े फ़ैसले लेने के लिए. इसके अलावा, सभी डिवाइसों पर वीडियो चलाने पर नज़र रखने के लिए, इस डेटा को किसी सर्वर पर भेजा जा सकता है.

आम तौर पर, किसी Analytics सिस्टम को पहले इवेंट इकट्ठा करने होते हैं. इसके बाद, उन्हें काम का बनाने के लिए, इन्हें प्रोसेस करना पड़ता है:

  • इवेंट कलेक्शन: ExoPlayer के किसी इंस्टेंस पर AnalyticsListener को रजिस्टर करके ऐसा किया जा सकता है. रजिस्टर किए गए Analytics लिसनर को, प्लेयर के इस्तेमाल के दौरान होने वाले इवेंट मिलते हैं. हर इवेंट, प्लेलिस्ट में मौजूद उस मीडिया आइटम से जुड़ा होता है जिस पर इवेंट हुआ है. साथ ही, यह प्लेबैक की पोज़िशन और टाइमस्टैंप मेटाडेटा से भी जुड़ा होता है.
  • इवेंट प्रोसेसिंग: कुछ आंकड़ों के सिस्टम, रॉ इवेंट को सर्वर पर अपलोड करते हैं. साथ ही, इवेंट की प्रोसेसिंग पूरी तरह से सर्वर-साइड पर की जाती है. इवेंट को डिवाइस पर भी प्रोसेस किया जा सकता है. ऐसा करने से, इवेंट को अपलोड करने की प्रक्रिया आसान हो सकती है या अपलोड की जाने वाली जानकारी की संख्या कम हो सकती है. ExoPlayer में PlaybackStatsListener उपलब्ध होता है. इसकी मदद से, प्रोसेस करने के ये चरण पूरे किए जा सकते हैं:
    1. इवेंट का विश्लेषण: विश्लेषण के लिए इवेंट का इस्तेमाल करने के लिए, इवेंट को एक ही वीडियो चलाने के संदर्भ में विश्लेषण करना ज़रूरी है. उदाहरण के लिए, प्लेयर की स्थिति के STATE_BUFFERING में बदलने के रॉ इवेंट से, शुरुआती बफ़रिंग, फिर से बफ़रिंग या किसी जगह पर जाने के बाद होने वाली बफ़रिंग के बारे में पता चल सकता है.
    2. स्टेट ट्रैकिंग: यह चरण, इवेंट को काउंटर में बदल देता है. उदाहरण के लिए, प्लेबैक की स्थिति में हुए बदलावों के इवेंट को काउंटर में बदला जा सकता है. इससे यह पता चलता है कि प्लेबैक की हर स्थिति में कितना समय बिताया गया. इसका नतीजा, एक बार चलाए गए वीडियो के लिए Analytics डेटा वैल्यू का बुनियादी सेट होता है.
    3. एग्रीगेशन: इस चरण में, कई वीडियो के विश्लेषण का डेटा एक साथ जोड़ा जाता है. आम तौर पर, ऐसा काउंटर जोड़कर किया जाता है.
    4. खास जानकारी वाली मेट्रिक का हिसाब लगाना: सबसे ज़्यादा काम की मेट्रिक में से कई ऐसी होती हैं जो औसत का हिसाब लगाती हैं या बुनियादी Analytics डेटा वैल्यू को दूसरे तरीकों से जोड़ती हैं. खास जानकारी वाली मेट्रिक का हिसाब, एक या एक से ज़्यादा प्लेबैक के लिए लगाया जा सकता है.

AnalyticsListener की मदद से इवेंट कलेक्शन

प्लेयर से मिले रॉ वीडियो चलाने के इवेंट, AnalyticsListener इंप्लिकेशन को रिपोर्ट किए जाते हैं. अपने हिसाब से आसानी से किसी भी Listener को जोड़ा जा सकता है. साथ ही, सिर्फ़ उन तरीकों को बदला जा सकता है जिनमें आपकी दिलचस्पी है:

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, इवेंट को प्लेलिस्ट में किसी मीडिया आइटम से जोड़ता है. साथ ही, वह वीडियो चलाने की पोज़िशन और टाइमस्टैंप मेटाडेटा से भी जुड़ा होता है:

  • realtimeMs: इवेंट का दीवार घड़ी वाला समय.
  • timeline, windowIndex, और mediaPeriodId: इवेंट से जुड़ी प्लेलिस्ट और उस प्लेलिस्ट में मौजूद आइटम के बारे में बताता है. mediaPeriodId में ऐसी अतिरिक्त जानकारी होती है जो ज़रूरी नहीं होती. उदाहरण के लिए, इससे पता चलता है कि इवेंट, आइटम में मौजूद किसी विज्ञापन से जुड़ा है या नहीं.
  • eventPlaybackPositionMs: इवेंट होने पर, आइटम में वीडियो चलाने की जगह.
  • currentTimeline, currentWindowIndex, currentMediaPeriodId, और currentPlaybackPositionMs: ऊपर बताए गए निर्देशों के मुताबिक, लेकिन फ़िलहाल चल रहे आइटम के लिए. फ़िलहाल चल रहा आइटम, उस आइटम से अलग हो सकता है जिससे इवेंट जुड़ा है. उदाहरण के लिए, अगर इवेंट, अगले आइटम को पहले से बफ़र करने से जुड़ा है.

PlaybackStatsListener की मदद से इवेंट प्रोसेस करना

PlaybackStatsListener एक AnalyticsListener है, जो ऑन-डिवाइस इवेंट प्रोसेसिंग को लागू करता है. यह काउंटर और व्युत्पन्न मेट्रिक के साथ PlaybackStats की गणना करता है, जिसमें ये शामिल हैं:

  • खास जानकारी वाली मेट्रिक, जैसे कि वीडियो चलाने का कुल समय.
  • अडैप्टिव प्लेबैक क्वालिटी से जुड़ी मेट्रिक, जैसे कि वीडियो का औसत रिज़ॉल्यूशन.
  • क्वालिटी मेट्रिक रेंडर करना, जैसे कि छूटे हुए फ़्रेम की दर.
  • संसाधन के इस्तेमाल से जुड़ी मेट्रिक, जैसे कि नेटवर्क पर पढ़े गए बाइट की संख्या.

आपको PlaybackStats Javadoc में, उपलब्ध गिनती और डेरिव्ड मेट्रिक की पूरी सूची दिखेगी.

PlaybackStatsListener, प्लेलिस्ट में मौजूद हर मीडिया आइटम के लिए अलग-अलग PlaybackStats कैलकुलेट करता है. साथ ही, इन आइटम में डाले गए हर क्लाइंट-साइड विज्ञापन के लिए भी अलग-अलग PlaybackStats कैलकुलेट करता है. PlaybackStatsListener को कॉलबैक दिया जा सकता है, ताकि आपको वीडियो के खत्म होने की जानकारी मिल सके. साथ ही, कॉलबैक में पास किए गए EventTime का इस्तेमाल करके, यह पता लगाया जा सकता है कि कौनसा वीडियो खत्म हुआ. एक से ज़्यादा बार चलाए जाने पर, Analytics डेटा इकट्ठा किया जा सकता है. PlaybackStatsListener.getPlaybackStats() का इस्तेमाल करके, किसी भी समय मौजूदा वीडियो चलाने के सेशन के लिए PlaybackStats से क्वेरी की जा सकती है.

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 का कन्स्ट्रक्टर, प्रोसेस किए गए इवेंट का पूरा इतिहास रखने का विकल्प देता है. ध्यान रखें कि वीडियो चलाने की अवधि और इवेंट की संख्या के हिसाब से, हो सकता है कि इससे मेमोरी के ऊपर एक अज्ञात अनुभव दिखे. इसलिए, आपको इसे सिर्फ़ तब चालू करना चाहिए, जब आपको सिर्फ़ फ़ाइनल आंकड़ों के डेटा के बजाय, प्रोसेस किए गए इवेंट के पूरे इतिहास को ऐक्सेस करना हो.

ध्यान दें कि PlaybackStats, मीडिया की स्थिति के साथ-साथ, उपयोगकर्ता के मीडिया चलाने के इंटेंट और ज़्यादा जानकारी के लिए, स्थितियों के बड़े सेट का इस्तेमाल करता है. जैसे, वीडियो चलाने में रुकावट क्यों आई या वीडियो खत्म क्यों हुआ:

वीडियो चलने की स्थिति गेम खेलने का उपयोगकर्ता का मकसद वीडियो चलाने का कोई इरादा नहीं है
वीडियो चलाने से पहले JOINING_FOREGROUND NOT_STARTED, JOINING_BACKGROUND
वीडियो चल रहा है PLAYING
गाने का प्लेबैक रुकना BUFFERING, SEEKING PAUSED, PAUSED_BUFFERING, SUPPRESSED, SUPPRESSED_BUFFERING, INTERRUPTED_BY_AD
खत्म होने की स्थितियां ENDED, STOPPED, FAILED, ABANDONED

वीडियो चलाने के उपयोगकर्ता के इंटेंट से यह पता चलता है कि वीडियो चलाने के लिए, उपयोगकर्ता ने कितनी बार 'वीडियो चलाएं' बटन को दबाया. उदाहरण के लिए, PlaybackStats.getTotalWaitTimeMs, JOINING_FOREGROUND, BUFFERING, और SEEKING स्थितियों में बिताया गया कुल समय दिखाता है. हालांकि, इसमें वीडियो चलाने के दौरान उसे रोकने का समय शामिल नहीं होता. इसी तरह, PlaybackStats.getTotalPlayAndWaitTimeMs, उपयोगकर्ता के गेम खेलने के इंटेंट के साथ कुल समय दिखाएगा. इसका मतलब है कि कुल सक्रिय इंतज़ार का समय और PLAYING स्टेटस में बिताया गया कुल समय.

प्रोसेस किए गए और व्याख्या किए गए इवेंट

PlaybackStatsListener के साथ keepHistory=true का इस्तेमाल करके, प्रोसेस किए गए और व्याख्या किए गए इवेंट रिकॉर्ड किए जा सकते हैं. नतीजे में मिलने वाले PlaybackStats में, इवेंट की ये सूचियां शामिल होंगी:

  • playbackStateHistory: वीडियो चलाने की अवधि बढ़ाने की स्थितियों की क्रम से लगाई गई सूची. साथ ही, EventTime भी शामिल है, जिस पर ये स्थितियां लागू हुईं. किसी तय समय पर स्टेटस देखने के लिए, PlaybackStats.getPlaybackStateAtTime का भी इस्तेमाल किया जा सकता है.
  • mediaTimeHistory: इसमें वॉल क्लॉक के समय और मीडिया के समय के जोड़े का इतिहास होता है. इससे यह पता चलता है कि मीडिया के कौनसे हिस्से किस समय चलाए गए थे. PlaybackStats.getMediaTimeMsAtRealtimeMs का इस्तेमाल करके, किसी तय समय पर वीडियो के चलने की स्थिति भी देखी जा सकती है.
  • videoFormatHistory और audioFormatHistory: वीडियो और ऑडियो फ़ॉर्मैट की क्रम से लगाई गई सूचियां. इनका इस्तेमाल, वीडियो चलाने के दौरान किया जाता है. साथ ही, इनके इस्तेमाल की शुरुआत के समय की जानकारी EventTime में दी जाती है.
  • fatalErrorHistory और nonFatalErrorHistory: EventTime से जुड़ी गंभीर और सामान्य गड़बड़ियों की क्रम से बनाई गई सूचियां. वीडियो चलाने में होने वाली गड़बड़ियों में, ऐसी गड़बड़ियां भी शामिल होती हैं जिनकी वजह से वीडियो चलाना बंद हो जाता है. वहीं, ऐसी गड़बड़ियां भी होती हैं जिनकी वजह से वीडियो चलाना जारी रखा जा सकता है.

सिंगल-प्लेबैक ऐनलिटिक्स डेटा

अगर आप PlaybackStatsListener का इस्तेमाल करते हैं, तो यह डेटा अपने-आप इकट्ठा हो जाता है. आप keepHistory=false के साथ भी ऐसा कर सकते हैं. आखिरी वैल्यू वे सार्वजनिक फ़ील्ड हैं जिन्हें PlaybackStats Javadoc में देखा जा सकता है. साथ ही, इन्हें getPlaybackStateDurationMs से दिखाई जाने वाली वीडियो चलाने की स्थिति की अवधि के तौर पर भी देखा जा सकता है. आपके लिए, getTotalPlayTimeMs और getTotalWaitTimeMs जैसे तरीके भी उपलब्ध हैं. इनसे, वीडियो चलाने की किसी खास स्थिति के कॉम्बिनेशन की अवधि पता चलती है.

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

एक से ज़्यादा बार चलाए गए वीडियो का कुल आंकड़ा

PlaybackStats.merge को कॉल करके, कई PlaybackStats को एक साथ जोड़ा जा सकता है. इस PlaybackStats में, मर्ज किए गए सभी वीडियो के डेटा को इकट्ठा किया जाएगा. ध्यान दें कि इसमें अलग-अलग प्लेबैक इवेंट का इतिहास शामिल नहीं होगा, क्योंकि इन इवेंट को एग्रीगेट नहीं किया जा सकता.

PlaybackStatsListener.getCombinedPlaybackStats का इस्तेमाल करके, आंकड़ों से जुड़ा सारा डेटा एक जगह पर देखा जा सकता है. यह डेटा PlaybackStatsListener के लाइफ़टाइम में इकट्ठा किया जाता है.

कैलकुलेट की गई खास जानकारी वाली मेट्रिक

बुनियादी आंकड़ों के डेटा के अलावा, PlaybackStats में खास जानकारी वाली मेट्रिक का हिसाब लगाने के कई तरीके उपलब्ध हैं.

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

बेहतर विषय

आंकड़ों का डेटा, वीडियो चलाने के मेटाडेटा से जोड़ना

अलग-अलग वीडियो के लिए आंकड़ों का डेटा इकट्ठा करते समय, हो सकता है कि आप वीडियो के आंकड़ों के डेटा को, चलाए जा रहे वीडियो के मेटाडेटा से जोड़ना चाहें.

हमारा सुझाव है कि MediaItem.Builder.setTag के साथ मीडिया के हिसाब से मेटाडेटा सेट करें. मीडिया टैग, रॉ इवेंट के लिए रिपोर्ट किए गए EventTime का हिस्सा होता है और जब PlaybackStats खत्म हो जाता है, तो इससे जुड़े आंकड़ों के डेटा को हैंडल करते समय, इसे आसानी से वापस पाया जा सकता है:

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

कस्टम Analytics इवेंट की रिपोर्टिंग

अगर आपको Analytics डेटा में कस्टम इवेंट जोड़ने हैं, तो आपको इन इवेंट को अपने डेटा स्ट्रक्चर में सेव करना होगा. इसके बाद, इन्हें बाद में रिपोर्ट किए गए PlaybackStats के साथ जोड़ना होगा. अगर इससे मदद मिलती है, तो DefaultAnalyticsCollector को बढ़ाया जा सकता है. इससे, कस्टम इवेंट के लिए EventTime इंस्टेंस जनरेट किए जा सकते हैं. साथ ही, उन्हें पहले से रजिस्टर किए गए लिसनर को भेजा जा सकता है. इसका उदाहरण नीचे दिया गया है.

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