प्रॉडक्ट से जुड़ी खबरें

मीडिया प्लेबैक को बेहतर बनाना: Media3 की मदद से प्रीलोडिंग की सुविधा के बारे में जानकारी - पहला भाग

आठ मिनट में पढ़ें
Mayuri Khinvasara Khabya
डेवलपर रिलेशंस इंजीनियर

आजकल मीडिया से जुड़े ऐप्लिकेशन में, बिना किसी रुकावट के वीडियो चलाने की सुविधा देना बहुत ज़रूरी है. इससे उपयोगकर्ताओं को बेहतर अनुभव मिलता है. उपयोगकर्ताओं को उम्मीद होती है कि वीडियो तुरंत शुरू हो जाएं और बिना किसी रुकावट के चलते रहें.

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

प्रीलोडिंग के मुख्य फ़ायदे ये हैं:

  • 🚀 वीडियो को तेज़ी से चलाना: वीडियो पहले से ही चलने के लिए तैयार होते हैं. इससे आइटम के बीच तेज़ी से ट्रांज़िशन होता है और वीडियो तुरंत शुरू हो जाता है.
  • 📉 बफ़रिंग कम होना: डेटा को पहले से लोड करने की वजह से, वीडियो के रुकने की संभावना कम हो जाती है. उदाहरण के लिए, नेटवर्क की समस्या की वजह से वीडियो रुकने की समस्या कम हो जाती है.
  • ✨ बेहतर उपयोगकर्ता अनुभव: वीडियो तेज़ी से शुरू होने और बफ़र होने में कम समय लगने की वजह से, उपयोगकर्ताओं को बेहतर अनुभव मिलता है.

तीन हिस्सों वाली इस सीरीज़ में, हम Media3 की उन बेहतरीन सुविधाओं के बारे में बताएंगे जो कॉम्पोनेंट को (प्री)लोड करने के लिए उपलब्ध हैं.

  • पहले भाग में, हम बुनियादी बातों के बारे में जानेंगे: Media3 में उपलब्ध अलग-अलग प्रीलोडिंग रणनीतियों को समझना, PreloadConfiguration को चालू करना, और DefaultPreloadManager को सेट अप करना. साथ ही, ऐप्लिकेशन को आइटम प्रीलोड करने की सुविधा देना. इस ब्लॉग को पढ़ने के बाद, आपको कॉन्फ़िगर की गई रैंकिंग और अवधि के हिसाब से मीडिया आइटम को प्रीलोड और चलाने का तरीका पता चल जाएगा.
  • दूसरे हिस्से में, हम DefaultPreloadManager के ज़्यादा बेहतर विषयों के बारे में जानेंगे. जैसे, आंकड़ों के लिए लिसनर का इस्तेमाल करना, प्रोडक्शन के लिए तैयार किए गए सबसे सही तरीकों के बारे में जानना. जैसे, स्लाइडिंग विंडो पैटर्न और DefaultPreloadManager और ExoPlayer के कस्टम शेयर किए गए कॉम्पोनेंट.
  • तीसरे हिस्से में, हम DefaultPreloadManager की मदद से डिस्क कैश मेमोरी के बारे में विस्तार से जानेंगे.

प्रीलोडिंग की सुविधा का इस्तेमाल करें! 🦸‍♀️

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

इसे किसी रेस्टोरेंट की तरह समझें. व्यस्त किचन में, प्याज़ काटने के लिए ऑर्डर का इंतज़ार नहीं किया जाता. 🧅 वे पहले से ही तैयारी कर लेते हैं. पहले से लोड करने की सुविधा, वीडियो प्लेयर के लिए तैयारी करने का काम करती है.

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

Media3 में, प्रीलोडिंग के लिए दो मुख्य एपीआई उपलब्ध हैं. ये दोनों एपीआई, इस्तेमाल के अलग-अलग उदाहरणों के लिए सही हैं. सही एपीआई चुनना पहला चरण है.

1. PreloadConfiguration की मदद से, प्लेलिस्ट के आइटम पहले से लोड करना

यह एक आसान तरीका है. यह लीनियर और क्रम से चलने वाले मीडिया के लिए फ़ायदेमंद है. जैसे, प्लेलिस्ट. इनमें प्लेबैक का क्रम अनुमान लगाया जा सकता है. जैसे, एपिसोड की कोई सीरीज़. ExoPlayer के playlist एपीआई का इस्तेमाल करके, प्लेयर को मीडिया आइटम की पूरी सूची दी जाती है. इसके बाद, प्लेयर के लिए PreloadConfiguration सेट किया जाता है. ऐसा करने पर, प्लेयर कॉन्फ़िगर किए गए क्रम के हिसाब से अगले आइटम अपने-आप प्रीलोड कर लेता है. यह एपीआई, जॉइन करने में लगने वाले समय को कम करने की कोशिश करता है. ऐसा तब होता है, जब कोई उपयोगकर्ता, पहले से ही अगले आइटम में ओवरलैप होने से पहले ही अगले आइटम पर चला जाता है.

प्रीलोडिंग सिर्फ़ तब शुरू होती है, जब मौजूदा प्लेबैक के लिए कोई मीडिया लोड नहीं किया जा रहा हो. इससे, प्रीलोडिंग को मुख्य प्लेबैक के साथ बैंडविड्थ के लिए प्रतिस्पर्धा करने से रोका जा सकता है.

अगर आपको अब भी पक्का नहीं है कि आपको प्रीलोडिंग की ज़रूरत है या नहीं, तो इस एपीआई को आज़माएं. यह एक बेहतरीन विकल्प है!

player.preloadConfiguration =
    PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)

ऊपर दिए गए PreloadConfiguration के साथ, प्लेयर प्लेलिस्ट में मौजूद अगले आइटम के लिए पांच सेकंड का मीडिया प्रीलोड करने की कोशिश करता है.

ऑप्ट-इन करने के बाद, प्लेलिस्ट को पहले से लोड करने की सुविधा को फिर से बंद किया जा सकता है. इसके लिए, PreloadConfiguration.DEFAULT का इस्तेमाल करके, प्लेलिस्ट को पहले से लोड करने की सुविधा बंद करें:

player.preloadConfiguration = PreloadConfiguration.DEFAULT

2. PreloadManager की मदद से डाइनैमिक सूचियों को पहले से लोड करना

वर्टिकल फ़ीड या कैरसेल जैसे डाइनैमिक यूज़र इंटरफ़ेस (यूआई) के लिए, PreloadManager API का इस्तेमाल किया जा सकता है. इनमें "अगला" आइटम, उपयोगकर्ता के इंटरैक्शन के आधार पर तय होता है. यह Media3 ExoPlayer लाइब्रेरी में मौजूद एक नया और दमदार स्टैंडअलोन कॉम्पोनेंट है. इसे खास तौर पर, पहले से लोड करने की सुविधा के लिए डिज़ाइन किया गया है. यह संभावित MediaSources के कलेक्शन को मैनेज करता है. साथ ही, उपयोगकर्ता की मौजूदा जगह के हिसाब से उन्हें प्राथमिकता देता है. यह प्रीलोड करने के लिए, ज़्यादा कंट्रोल देता है. यह छोटे वीडियो के डाइनैमिक फ़ीड जैसे मुश्किल मामलों के लिए सही है.

PreloadManager को सेट अप करना

DefaultPreloadManager, PreloadManager के लिए कैननिकल तरीके से लागू किया गया है.

DefaultPreloadManager को बनाने वाला व्यक्ति, DefaultPreloadManager और ExoPlayer के ऐसे इंस्टेंस बना सकता है जो पहले से लोड किए गए कॉन्टेंट को चलाएंगे. DefaultPreloadManager बनाने के लिए, आपको TargetPreloadStatusControl पास करना होगा. प्रीलोड मैनेजर, इस कंट्रोल से यह क्वेरी कर सकता है कि किसी आइटम के लिए कितना डेटा लोड करना है. हम नीचे दिए गए सेक्शन में, TargetPreloadStatusControl का उदाहरण देंगे और इसके बारे में बताएंगे.

val preloadManagerBuilder =
DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = val preloadManagerBuilder.build()

// Build ExoPlayer with DefaultPreloadManager.Builder
val player = preloadManagerBuilder.buildExoPlayer()

ExoPlayer और DefaultPreloadManager, दोनों के लिए एक ही बिल्डर का इस्तेमाल करना ज़रूरी है. इससे यह पक्का होता है कि इनके कॉम्पोनेंट सही तरीके से शेयर किए गए हैं.

यह बहुत आसान है! अब आपके पास एक मैनेजर है, जो निर्देश पाने के लिए तैयार है.

TargetPreloadStatusControl की मदद से, अवधि और रैंकिंग कॉन्फ़िगर करना

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

अगर आपको यह कंट्रोल करना है कि आइटम को कितनी अवधि के लिए प्रीलोड करना है, तो DefaultPreloadManager.PreloadStatus का इस्तेमाल करके यह जानकारी दी जा सकती है.

जैसे, मुझे पता चला कि

  • आइटम ‘A’ को सबसे ज़्यादा प्राथमिकता दी गई है. इसलिए, वीडियो के पांच सेकंड लोड किए गए हैं.
  • आइटम ‘B’ को सामान्य प्राथमिकता दी गई है. हालांकि, जब आप इस पर पहुंचें, तो तीन सेकंड का वीडियो लोड करें.
  • आइटम ‘C’ को कम प्राथमिकता दी गई है. सिर्फ़ ट्रैक लोड करें.
  • आइटम ‘D’ को और भी कम प्राथमिकता दी गई है. बस तैयारी करें.
  • कोई अन्य आइटम बहुत दूर है. किसी भी आइटम को पहले से लोड न करें.

इस कंट्रोल की मदद से, संसाधनों का बेहतर तरीके से इस्तेमाल किया जा सकता है. इससे वीडियो को बिना किसी रुकावट के चलाने में मदद मिलती है.

import androidx.media3.exoplayer.DefaultPreloadManager.PreloadStatus


class MyTargetPreloadStatusControl(
    currentPlayingIndex: Int = C.INDEX_UNSET
) : TargetPreloadStatusControl<Int,PreloadStatus> {


    // The app is responsible for updating this based on UI state
    override fun getTargetPreloadStatus(index: Int): PreloadStatus? {

        val distance = index - currentPlayingIndex

        // Adjacent items (Next): preload 5 seconds
        if (distance == 1) { 
        // Return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and suggest loading // 5000ms from the default start position
                    return PreloadStatus.specifiedRangeLoaded(5000L)
                } 

        // Adjacent items (Previous): preload 3 seconds
        else if (distance == -1) { 
        // Return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED //and suggest loading 3000ms from the default start position
                    return PreloadStatus.specifiedRangeLoaded(3000L)
                } 

        // Items two positions away: just select tracks
        else if (distance) == 2) {
        // Return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
                    return PreloadStatus.TRACKS_SELECTED
                } 

        // Items four positions away: just select prepare
        else if (abs(distance) <= 4) {
        // Return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
                    return PreloadStatus.SOURCE_PREPARED
                }

             // All other items are too far away
             return null
            }
}

अहम जानकारी: PreloadManager, पिछले और अगले आइटम, दोनों को पहले से लोड करके रख सकता है. वहीं, PreloadConfiguration सिर्फ़ अगले आइटम को पहले से लोड करके रखेगा.

पहले से लोड किए गए आइटम मैनेज करना

मैनेजर खाता बनाने के बाद, उसे यह बताया जा सकता है कि उसे क्या काम करना है. जब उपयोगकर्ता फ़ीड में स्क्रोल करता है, तब आपको आने वाले वीडियो की पहचान करनी होगी. इसके बाद, उन्हें मैनेजर में जोड़ना होगा. PreloadManager के साथ इंटरैक्शन, आपके यूज़र इंटरफ़ेस (यूआई) और प्रीलोडिंग इंजन के बीच की बातचीत होती है.

1. मीडिया आइटम जोड़ें

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

val initialMediaItems = pullMediaItemsFromService(/* count= */ 20)
for (index in 0 until initialMediaItems.size) {
    preloadManager.add(
        initialMediaItems.get(index),index)
    )
}

अब मैनेजर, बैकग्राउंड में इस MediaItem के लिए डेटा फ़ेच करना शुरू कर देगा.

जोड़ने के बाद, मैनेजर को नई सूची का फिर से आकलन करने के लिए कहें. इससे उसे पता चलेगा कि कुछ बदलाव हुआ है. जैसे, कोई आइटम जोड़ा/ हटाया गया है या उपयोगकर्ता ने कोई नया आइटम चलाना शुरू कर दिया है.

preloadManager.invalidate()

2. किसी आइटम को वापस पाना और उसे चलाना

यहां मुख्य प्लेबैक लॉजिक दिया गया है. जब उपयोगकर्ता उस वीडियो को चलाने का फ़ैसला करता है, तब आपको नया MediaSource बनाने की ज़रूरत नहीं होती. इसके बजाय, PreloadManager से उस जवाब के बारे में पूछें जो उसने पहले ही तैयार कर लिया है. MediaItem का इस्तेमाल करके, Preload Manager से MediaSource को वापस पाया जा सकता है.

अगर PreloadManager से वापस मिला आइटम null है, तो इसका मतलब है कि mediaItem को अब तक प्रीलोड नहीं किया गया है या उसे PreloadMamager में नहीं जोड़ा गया है. इसलिए, आपके पास mediaItem को सीधे तौर पर सेट करने का विकल्प होता है.

// When a media item is about to displ​​ay on the screen
val mediaSource = preloadManager.getMediaSource(mediaItem)
if (mediaSource!= null) {
  player.setMediaSource(mediaSource)
} else {
  // If mediaSource is null, that mediaItem hasn't been added yet.
  // So, send it directly to the player.
  player.setMediaItem(mediaItem)
}
player.prepare()
// When the media item is displaying at the center of the screen
player.play()

PreloadManager से वापस पाए गए MediaSource को तैयार करके, प्रीलोडिंग से लेकर प्लेबैक तक आसानी से ट्रांज़िशन किया जा सकता है. इसके लिए, मेमोरी में पहले से मौजूद डेटा का इस्तेमाल किया जाता है. इसी वजह से, वीडियो के शुरू होने में कम समय लगता है.

3. मौजूदा इंडेक्स को यूज़र इंटरफ़ेस (यूआई) के साथ सिंक करके रखें

हमारा फ़ीड / सूची डाइनैमिक हो सकती है. इसलिए, PreloadManager को मौजूदा इंडेक्स के बारे में सूचना देना ज़रूरी है, ताकि वह हमेशा प्रीलोड करने के लिए, आपके मौजूदा इंडेक्स के सबसे नज़दीकी आइटम को प्राथमिकता दे सके.

preloadManager.setCurrentPlayingIndex(currentIndex)
// Need to call invalidate() to update the priorities
preloadManager.invalidate()

4. कोई आइटम हटाना

मैनेजर को बेहतर तरीके से काम करने देने के लिए, आपको उन आइटम को हटा देना चाहिए जिन्हें अब ट्रैक करने की ज़रूरत नहीं है. जैसे, वे आइटम जो उपयोगकर्ता की मौजूदा जगह से बहुत दूर हैं.

// When an item is too far from the current playing index
preloadManager.remove(mediaItem)

अगर आपको एक साथ सभी आइटम हटाने हैं, तो preloadManager.reset() को कॉल करें.

5. मैनेजर को रिलीज़ करें

जब आपको PreloadManager की ज़रूरत न हो (जैसे, जब आपका यूज़र इंटरफ़ेस (यूआई) बंद हो जाता है), तो आपको इसे रिलीज़ करना होगा, ताकि इसके संसाधनों को खाली किया जा सके. इसके लिए, वह जगह सबसे सही होती है जहां आपने पहले से ही प्लेयर के रिसॉर्स रिलीज़ किए हुए हैं. हमारा सुझाव है कि प्लेयर को रिलीज़ करने से पहले मैनेजर को रिलीज़ करें. ऐसा इसलिए, क्योंकि अगर आपको प्रीलोडिंग की ज़रूरत नहीं है, तो प्लेयर खेलना जारी रख सकता है.

// In your Activity's onDestroy() or Composable's onDispose
preloadManager.release()

डेमो का समय

इसे लाइव में काम करते हुए देखें 👍

नीचे दिए गए डेमो में , दाईं ओर PreloadManager का असर दिख रहा है. इसमें पेज लोड होने में कम समय लगता है. वहीं, बाईं ओर मौजूदा अनुभव दिख रहा है. डेमो के लिए, कोड का सैंपल भी देखा जा सकता है. (बोनस: यह हर वीडियो के लिए स्टार्टअप लेटेंसी भी दिखाता है)

Demo-PreloadManager_2.webp

अगला चरण?

पहले हिस्से में बस इतना ही! अब आपके पास डाइनैमिक प्रीलोडिंग सिस्टम बनाने के लिए टूल हैं. ExoPlayer में किसी प्लेलिस्ट के अगले आइटम को प्रीलोड करने के लिए, PreloadConfiguration का इस्तेमाल किया जा सकता है. इसके अलावा, PreloadConfiguration को सेट अप किया जा सकता है. साथ ही, आइटम को तुरंत जोड़ा और हटाया जा सकता है. इसके अलावा, प्रीलोड करने की स्थिति को कॉन्फ़िगर किया जा सकता है. साथ ही, प्रीलोड किए गए कॉन्टेंट को वापस पाने के लिए, उसे सही तरीके से चलाया जा सकता है.DefaultPreloadManager

दूसरे हिस्से में, हम DefaultPreloadManager के बारे में ज़्यादा जानकारी देंगे. हम प्रीलोडिंग इवेंट को सुनने के तरीके के बारे में जानेंगे. साथ ही, मेमोरी से जुड़ी समस्याओं से बचने के लिए, स्लाइडिंग विंडो का इस्तेमाल करने जैसे सबसे सही तरीकों पर चर्चा करेंगे. इसके अलावा, हम ExoPlayer और DefaultPreloadManager के कस्टम शेयर किए गए कॉम्पोनेंट के बारे में भी जानेंगे.

क्या आपको कोई सुझाव, शिकायत या राय भेजनी है? हमें आपके जवाब का इंतज़ार रहेगा.

हमारे साथ बने रहें और अपने ऐप्लिकेशन को ज़्यादा तेज़ बनाएँ! 🚀

इसे लिखा है:

पढ़ना जारी रखें