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

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

पढ़ने में 8 मिनट लगेंगे
मयूरी खिनवासरा खाब्या की प्रोफ़ाइल देखें
Mayuri Khinvasara Khabya डेवलपर रिलेशंस इंजीनियर

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

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

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

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

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

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

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

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

लेखक:
पढ़ना जारी रखें