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

मीडिया चलाने की सुविधा को बेहतर बनाना: Media3 के साथ प्रीलोडिंग की सुविधा लॉन्च करना - पहला हिस्सा

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

player.preloadConfiguration = PreloadConfiguration.DEFAULT

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

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

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 से वापस पाया गया आइटम, नल है, तो इसका मतलब है कि 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 की ज़रूरत न हो (जैसे, जब आपका यूज़र इंटरफ़ेस (यूआई) बंद हो जाता है), तो उसके रिसॉर्स को खाली करने के लिए, उसे रिलीज़ करना ज़रूरी है. ऐसा करने के लिए, वह जगह सही है जहां आपने Player के रिसॉर्स को पहले से ही रिलीज़ किया है. हमारा सुझाव है कि प्लेयर से पहले मैनेजर को रिलीज़ करें, क्योंकि अगर आपको अब प्रीलोडिंग की ज़रूरत नहीं है, तो प्लेयर वीडियो चलाना जारी रख सकता है.

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

डेमो का समय

इसे लाइव देखें 👍

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

Demo-PreloadManager_2.webp

अगला चरण?

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

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

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

अप-टू-डेट रहें और अपने ऐप्लिकेशन को ज़्यादा तेज़ बनाएं! 🚀

इसे लिखा है:

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