ExoPlayer, वीडियो चलाने से जुड़े आंकड़े इकट्ठा करने की कई ज़रूरतों को पूरा करता है. आखिर में, आंकड़ों का मतलब वीडियो चलाने से जुड़ा डेटा इकट्ठा करना, उसका विश्लेषण करना, उसे इकट्ठा करना, और खास जानकारी के तौर पर दिखाना है. इस डेटा का इस्तेमाल, डिवाइस पर किया जा सकता है. उदाहरण के लिए, लॉग करने, डीबग करने या आने वाले समय में वीडियो चलाने से जुड़े फ़ैसले लेने के लिए. इसके अलावा, सभी डिवाइसों पर वीडियो चलाने पर नज़र रखने के लिए, इस डेटा को किसी सर्वर पर भेजा जा सकता है.
आम तौर पर, किसी Analytics सिस्टम को पहले इवेंट इकट्ठा करने होते हैं. इसके बाद, उन्हें काम का बनाने के लिए, इन्हें प्रोसेस करना पड़ता है:
- इवेंट कलेक्शन:
ExoPlayer
के किसी इंस्टेंस परAnalyticsListener
को रजिस्टर करके ऐसा किया जा सकता है. रजिस्टर किए गए Analytics लिसनर को, प्लेयर के इस्तेमाल के दौरान होने वाले इवेंट मिलते हैं. हर इवेंट, प्लेलिस्ट में मौजूद उस मीडिया आइटम से जुड़ा होता है जिस पर इवेंट हुआ है. साथ ही, यह प्लेबैक की पोज़िशन और टाइमस्टैंप मेटाडेटा से भी जुड़ा होता है. - इवेंट प्रोसेसिंग: कुछ आंकड़ों के सिस्टम, रॉ इवेंट को सर्वर पर अपलोड करते हैं. साथ ही, इवेंट की प्रोसेसिंग पूरी तरह से सर्वर-साइड पर की जाती है. इवेंट को डिवाइस पर भी प्रोसेस किया जा सकता है. ऐसा करने से, इवेंट को अपलोड करने की प्रक्रिया आसान हो सकती है या अपलोड की जाने वाली जानकारी की संख्या कम हो सकती है. ExoPlayer में
PlaybackStatsListener
उपलब्ध होता है. इसकी मदद से, प्रोसेस करने के ये चरण पूरे किए जा सकते हैं:- इवेंट का विश्लेषण: विश्लेषण के लिए इवेंट का इस्तेमाल करने के लिए, इवेंट को एक ही वीडियो चलाने के संदर्भ में विश्लेषण करना ज़रूरी है. उदाहरण के लिए, प्लेयर की स्थिति के
STATE_BUFFERING
में बदलने के रॉ इवेंट से, शुरुआती बफ़रिंग, फिर से बफ़रिंग या किसी जगह पर जाने के बाद होने वाली बफ़रिंग के बारे में पता चल सकता है. - स्टेट ट्रैकिंग: यह चरण, इवेंट को काउंटर में बदल देता है. उदाहरण के लिए, प्लेबैक की स्थिति में हुए बदलावों के इवेंट को काउंटर में बदला जा सकता है. इससे यह पता चलता है कि प्लेबैक की हर स्थिति में कितना समय बिताया गया. इसका नतीजा, एक बार चलाए गए वीडियो के लिए Analytics डेटा वैल्यू का बुनियादी सेट होता है.
- एग्रीगेशन: इस चरण में, कई वीडियो के विश्लेषण का डेटा एक साथ जोड़ा जाता है. आम तौर पर, ऐसा काउंटर जोड़कर किया जाता है.
- खास जानकारी वाली मेट्रिक का हिसाब लगाना: सबसे ज़्यादा काम की मेट्रिक में से कई ऐसी होती हैं जो औसत का हिसाब लगाती हैं या बुनियादी 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();