नेटवर्क स्टैक

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

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

किसी खास नेटवर्क स्टैक का इस्तेमाल करने के लिए, ExoPlayer को कॉन्फ़िगर करना

ExoPlayer, DataSource कॉम्पोनेंट के ज़रिए डेटा लोड करता है. यह डेटा, उसे DataSource.Factory इंस्टेंस से मिलता है. ये इंस्टेंस, ऐप्लिकेशन कोड से इंजेक्ट किए जाते हैं.

अगर आपके ऐप्लिकेशन को सिर्फ़ http(s) कॉन्टेंट चलाना है, तो नेटवर्क स्टैक चुनना उतना ही आसान है जितना कि उन DataSource.Factory इंस्टेंस को अपडेट करना जिन्हें आपका ऐप्लिकेशन, DataSource.Factory के इंस्टेंस के तौर पर इंजेक्ट करता है. यह DataSource.Factory, उस नेटवर्क स्टैक से मेल खाता है जिसका आपको इस्तेमाल करना है.HttpDataSource.Factory अगर आपके ऐप्लिकेशन को लोकल फ़ाइलों जैसे नॉन-एचटीटीपी(एस) कॉन्टेंट को भी चलाना है, तो DefaultDataSource.Factory का इस्तेमाल करें:

Kotlin

DefaultDataSource.Factory(
  ...
  /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))

Java

new DefaultDataSource.Factory(
    ...
    /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));

इस उदाहरण में, PreferredHttpDataSource.Factory वह फ़ैक्ट्री है जो आपके पसंदीदा नेटवर्क स्टैक से जुड़ी है. DefaultDataSource.Factory लेयर, लोकल फ़ाइलों जैसे नॉन-एचटीटीपी(एस) सोर्स के लिए सहायता जोड़ती है.

यहां दिए गए उदाहरण में, ExoPlayer बनाने का तरीका बताया गया है. यह Cronet नेटवर्क स्टैक का इस्तेमाल करेगा. साथ ही, यह नॉन-http(s) कॉन्टेंट को चलाने की सुविधा भी देगा.

Kotlin

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor)

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
val dataSourceFactory =
  DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
CronetDataSource.Factory cronetDataSourceFactory =
    new CronetDataSource.Factory(cronetEngine, executor);

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
DefaultDataSource.Factory dataSourceFactory =
    new DefaultDataSource.Factory(
        context, /* baseDataSourceFactory= */ cronetDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

साथ काम करने वाले नेटवर्क स्टैक

ExoPlayer, HttpEngine, Cronet, OkHttp, और Android के बिल्ट-इन डिफ़ॉल्ट नेटवर्क स्टैक के साथ सीधे तौर पर काम करता है. ExoPlayer को Android पर काम करने वाले किसी भी अन्य नेटवर्क स्टैक के साथ इस्तेमाल किया जा सकता है.

HttpEngine

HttpEngine Android के एपीआई 34 (या S एक्सटेंशन 7) पर, सुझाया गया डिफ़ॉल्ट नेटवर्क स्टैक है. ज़्यादातर मामलों में, यह अंदरूनी तौर पर Cronet नेटवर्क स्टैक का इस्तेमाल करता है. यह QUIC प्रोटोकॉल पर एचटीटीपी, एचटीटीपी/2, और एचटीटीपी/3 के साथ काम करता है.

ExoPlayer, HttpEngineDataSource.Factory के साथ HttpEngine का इस्तेमाल करने की सुविधा देता है. किसी खास नेटवर्क स्टैक का इस्तेमाल करने के लिए ExoPlayer को कॉन्फ़िगर करना में बताए गए तरीके से, इस डेटा सोर्स फ़ैक्ट्री को इंजेक्ट किया जा सकता है.

Cronet

Cronet, Chromium का नेटवर्क स्टैक है. इसे Android ऐप्लिकेशन के लिए लाइब्रेरी के तौर पर उपलब्ध कराया जाता है. Cronet, कई टेक्नोलॉजी का इस्तेमाल करता है. इससे, आपके ऐप्लिकेशन को काम करने के लिए ज़रूरी नेटवर्क अनुरोधों के इंतज़ार का समय कम हो जाता है और थ्रूपुट बढ़ जाता है. इनमें ExoPlayer के किए गए अनुरोध भी शामिल हैं. यह एचटीटीपी, एचटीटीपी/2, और क्यूयूआईसी प्रोटोकॉल पर एचटीटीपी/3 के साथ काम करता है. Cronet का इस्तेमाल दुनिया के कुछ सबसे बड़े स्ट्रीमिंग ऐप्लिकेशन करते हैं. इनमें YouTube भी शामिल है.

ExoPlayer, Cronet लाइब्रेरी के ज़रिए Cronet के साथ काम करता है. इसे इस्तेमाल करने के तरीके के बारे में ज़्यादा जानकारी के लिए, लाइब्रेरी का README.md देखें. ध्यान दें कि Cronet लाइब्रेरी, Cronet के तीन बुनियादी वर्शन का इस्तेमाल कर सकती है:

  1. Google Play Services: हम ज़्यादातर मामलों में, इस सुविधा का इस्तेमाल करने का सुझाव देते हैं. अगर Google Play Services उपलब्ध नहीं है, तो Android के बिल्ट-इन नेटवर्क स्टैक (DefaultHttpDataSource) का इस्तेमाल करें.
  2. Cronet Embedded: अगर आपके ज़्यादातर उपयोगकर्ता ऐसे देशों/इलाकों में हैं जहां Google Play services बड़े पैमाने पर उपलब्ध नहीं है या आपको इस्तेमाल किए जा रहे Cronet के वर्शन को कंट्रोल करना है, तो यह विकल्प आपके लिए सही हो सकता है. Cronet Embedded का सबसे बड़ा नुकसान यह है कि यह आपके ऐप्लिकेशन में करीब 8 एमबी जोड़ देता है.
  3. Cronet फ़ॉलबैक: Cronet के फ़ॉलबैक को लागू करने के लिए, Android के बिल्ट-इन नेटवर्क स्टैक के चारों ओर रैपर के तौर पर Cronet के एपीआई को लागू किया जाता है. इसका इस्तेमाल ExoPlayer के साथ नहीं किया जाना चाहिए, क्योंकि Android के पहले से मौजूद नेटवर्क स्टैक का सीधे तौर पर इस्तेमाल करना (DefaultHttpDataSource का इस्तेमाल करके) ज़्यादा असरदार होता है.

OkHttp

OkHttp एक और मॉडर्न नेटवर्क स्टैक है. इसका इस्तेमाल कई लोकप्रिय Android ऐप्लिकेशन में बड़े पैमाने पर किया जाता है. यह एचटीटीपी और एचटीटीपी/2 के साथ काम करता है. हालांकि, यह फ़िलहाल क्यूयूआईसी पर एचटीटीपी/3 के साथ काम नहीं करता.

ExoPlayer, OkHttp लाइब्रेरी के ज़रिए OkHttp के साथ काम करता है. इसे इस्तेमाल करने के तरीके के बारे में ज़्यादा जानकारी के लिए, लाइब्रेरी का README.md देखें. OkHttp लाइब्रेरी का इस्तेमाल करने पर, नेटवर्क स्टैक को ऐप्लिकेशन में एम्बेड किया जाता है. यह Cronet Embedded की तरह ही होता है. हालांकि, OkHttp का साइज़ काफ़ी छोटा होता है. यह आपके ऐप्लिकेशन में 1 एमबी से भी कम जगह लेता है.

Android में पहले से मौजूद नेटवर्क स्टैक

ExoPlayer, Android के बिल्ट-इन नेटवर्क स्टैक के साथ काम करता है. इसके लिए, DefaultHttpDataSource और DefaultHttpDataSource.Factory का इस्तेमाल किया जाता है. ये दोनों, ExoPlayer की मुख्य लाइब्रेरी का हिस्सा हैं.

नेटवर्क स्टैक को लागू करने का सटीक तरीका, उस सॉफ़्टवेयर पर निर्भर करता है जो डिवाइस पर चल रहा है. ज़्यादातर डिवाइसों पर सिर्फ़ एचटीटीपी काम करता है. इसका मतलब है कि QUIC पर एचटीटीपी/2 और एचटीटीपी/3 काम नहीं करते.

अन्य नेटवर्क स्टैक

ऐप्लिकेशन, ExoPlayer के साथ अन्य नेटवर्क स्टैक भी इंटिग्रेट कर सकते हैं. इसके लिए, नेटवर्क स्टैक को रैप करने वाले HttpDataSource को लागू करें. साथ ही, इससे जुड़ा HttpDataSource.Factory भी लागू करें. ExoPlayer की Cronet और OkHttp लाइब्रेरी, इसके सबसे अच्छे उदाहरण हैं.

प्योर Java नेटवर्क स्टैक के साथ इंटिग्रेट करते समय, DataSourceContractTest को लागू करना एक अच्छा तरीका है. इससे यह जांच की जा सकती है कि HttpDataSource को लागू करने पर, वह सही तरीके से काम कर रहा है या नहीं. OkHttp लाइब्रेरी में OkHttpDataSourceContractTest इसका एक अच्छा उदाहरण है.

नेटवर्क स्टैक चुनना

यहां दी गई टेबल में, ExoPlayer के साथ काम करने वाले नेटवर्क स्टैक के फ़ायदे और नुकसान के बारे में बताया गया है.

नेटवर्क स्टैक प्रोटोकॉल APK के साइज़ का असर नोट
HttpEngine HTTP
HTTP/2
QUIC पर HTTP/3
कोई नहीं सिर्फ़ एपीआई 34 या S Extensions 7 पर उपलब्ध है
Cronet (Google Play services) HTTP
HTTP/2
QUIC पर HTTP/3
छोटा
(<100 केबी)
इसके लिए, Google Play services की ज़रूरत होती है. Cronet का वर्शन अपने-आप अपडेट हो गया
Cronet (एम्बेड किया गया) HTTP
HTTP/2
QUIC पर HTTP/3
बड़ा
(~8एमबी)
ऐप्लिकेशन डेवलपर के पास Cronet के वर्शन को कंट्रोल करने का विकल्प होता है
Cronet (फ़ॉलबैक) एचटीटीपी
(डिवाइस के हिसाब से अलग-अलग होता है)
छोटा
(<100 केबी)
ExoPlayer के लिए इसका सुझाव नहीं दिया जाता
OkHttp HTTP
HTTP/2
छोटा
(<1MB)
पहले से मौजूद नेटवर्क स्टैक एचटीटीपी
(डिवाइस के हिसाब से अलग-अलग होता है)
कोई नहीं डिवाइस के हिसाब से लागू करने का तरीका अलग-अलग होता है

QUIC प्रोटोकॉल पर एचटीटीपी/2 और एचटीटीपी/3 प्रोटोकॉल का इस्तेमाल करने से, मीडिया स्ट्रीमिंग की परफ़ॉर्मेंस में काफ़ी सुधार हो सकता है. खास तौर पर, जब कॉन्टेंट डिलीवरी नेटवर्क (सीडीएन) का इस्तेमाल करके अडैप्टिव मीडिया को स्ट्रीम किया जाता है, तो ऐसे मामलों में इन प्रोटोकॉल का इस्तेमाल करने से सीडीएन ज़्यादा बेहतर तरीके से काम कर सकते हैं. इस वजह से, Android के बिल्ट-इन नेटवर्क स्टैक का इस्तेमाल करने के मुकाबले, HttpEngine और Cronet के साथ-साथ OkHttp के लिए HTTP/2 और HTTP/3 को QUIC पर इस्तेमाल करने की सुविधा एक बड़ा फ़ायदा है. हालांकि, यह सुविधा तब ही काम करेगी, जब कॉन्टेंट होस्ट करने वाले सर्वर भी इन प्रोटोकॉल के साथ काम करते हों.

सिर्फ़ मीडिया स्ट्रीमिंग के लिए, हमारा सुझाव है कि Google Play services की ओर से उपलब्ध कराए गए HttpEngine या Cronet का इस्तेमाल करें. अगर Google Play services उपलब्ध नहीं है, तो DefaultHttpDataSource का इस्तेमाल करें. इस सुझाव में, ज़्यादातर डिवाइसों पर क्यूयूआईसी के ज़रिए एचटीटीपी/2 और एचटीटीपी/3 का इस्तेमाल करने और एपीके के साइज़ में काफ़ी बढ़ोतरी से बचने के बीच अच्छा संतुलन बनाया गया है. इस सुझाव के कुछ अपवाद हैं. अगर आपके ऐप्लिकेशन को चलाने वाले ज़्यादातर डिवाइसों पर Google Play Services उपलब्ध नहीं है, तो Cronet Embedded या OkHttp का इस्तेमाल करना ज़्यादा सही हो सकता है. अगर APK का साइज़ एक अहम समस्या है या मीडिया स्ट्रीमिंग, आपके ऐप्लिकेशन के मुख्य फ़ंक्शन का सिर्फ़ एक छोटा हिस्सा है, तो बिल्ट-इन नेटवर्क स्टैक का इस्तेमाल किया जा सकता है.

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

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

मीडिया को कैश मेमोरी में सेव करना

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

कैश मेमोरी में सेव करने के लिए, SimpleCache इंस्टेंस को किसी खास कैश मेमोरी वाली डायरेक्ट्री और CacheDataSource.Factory की ओर पॉइंट करना ज़रूरी है:

Kotlin

// Note: This should be a singleton in your app.
val databaseProvider = StandaloneDatabaseProvider(context)

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
val cache =
    SimpleCache(
        downloadDirectory, LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider)

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
val cacheDataSourceFactory =
    CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
    ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build()

Java

// Note: This should be a singleton in your app.
DatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
Cache cache =
    new SimpleCache(
        downloadDirectory, new LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider);

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
DataSource.Factory cacheDataSourceFactory =
    new CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build();