कस्टमाइज़ेशन

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

  • MediaSource इंस्टेंस जो चलाए जाने के लिए मीडिया तय करते हैं, मीडिया लोड करते हैं, और जिससे लोड किए गए मीडिया को पढ़ा जा सके. MediaSource इंस्टेंस बनाया गया प्लेयर के अंदर, MediaSource.Factory से MediaItem से. वे यह भी कर सकते हैं मीडिया सोर्स पर आधारित प्लेलिस्ट एपीआई का इस्तेमाल करके, सीधे प्लेयर को पास किया जाना चाहिए.
  • MediaSource.Factory इंस्टेंस, जो MediaItem को MediaSource में बदलता है. कॉन्टेंट बनाने प्लेयर बनाए जाने के बाद, MediaSource.Factory को इंजेक्ट किया जाता है.
  • Renderer इंस्टेंस, जो मीडिया के अलग-अलग कॉम्पोनेंट को रेंडर करते हैं. ये हैं प्लेयर बनाते समय इंजेक्ट किया जाता है.
  • एक TrackSelector जो MediaSource के दिए गए ट्रैक को हर उपलब्ध Renderer के इस्तेमाल करने वाले लोग. TrackSelector इंजेक्ट किया गया है जब प्लेयर बनाया जाता है.
  • LoadControl, जो यह कंट्रोल करता है कि MediaSource कब ज़्यादा मीडिया बफ़र करता है और मीडिया कितनी बार बफ़र किया गया है. LoadControl तब इंजेक्ट किया जाता है, जब प्लेयर बनाया गया.
  • LivePlaybackSpeedControl, जो लाइव स्ट्रीम के दौरान वीडियो चलाने की स्पीड को कंट्रोल करता है कॉन्फ़िगर किए गए लाइव ऑफ़सेट के करीब रहने के लिए, वीडियो चलाना. ऐप्लिकेशन प्लेयर बनाए जाने के बाद, LivePlaybackSpeedControl को इंजेक्ट किया जाता है.

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

प्लेयर को पसंद के मुताबिक बनाएं

कॉम्पोनेंट को इंजेक्ट करके, प्लेयर को पसंद के मुताबिक बनाने के कुछ उदाहरण यहां दिए गए हैं जिनकी जानकारी नीचे दी गई है.

नेटवर्क स्टैक को कॉन्फ़िगर करना

हमारे पास ExoPlayer पर इस्तेमाल किए जाने वाले नेटवर्क स्टैक को पसंद के मुताबिक बनाने के बारे में एक पेज है.

नेटवर्क से लोड किए गए डेटा को कैश मेमोरी में सेव करना

इसके लिए, गाइड देखें कुछ समय के लिए तुरंत कैश मेमोरी में सेव होने की सुविधा और मीडिया डाउनलोड करना होगा.

सर्वर के इंटरैक्शन को पसंद के मुताबिक बनाना

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

नीचे दिए गए उदाहरण में, इन तरीकों को इस्तेमाल करने का तरीका बताया गया है DefaultMediaSourceFactory में पसंद के मुताबिक DataSource.Factory को इंजेक्ट करना:

Kotlin

val dataSourceFactory =
  DataSource.Factory {
    val dataSource = httpDataSourceFactory.createDataSource()
    // Set a custom authentication request header.
    dataSource.setRequestProperty("Header", "Value")
    dataSource
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

DataSource.Factory dataSourceFactory =
    () -> {
      HttpDataSource dataSource = httpDataSourceFactory.createDataSource();
      // Set a custom authentication request header.
      dataSource.setRequestProperty("Header", "Value");
      return dataSource;
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

ऊपर दिए गए कोड स्निपेट में, इंजेक्ट किए गए HttpDataSource में हेडर शामिल है हर एचटीटीपी अनुरोध में "Header: Value". यह व्यवहार तय है, किसी एचटीटीपी सोर्स के साथ इंटरैक्शन करना चाहिए.

ज़्यादा बारीकी से जानकारी पाने के लिए, 'टाइम-इन-टाइम' व्यवहार को इंजेक्ट किया जा सकता है. इसके लिए ResolvingDataSource. नीचे दिया गया कोड स्निपेट, इंजेक्ट करने का तरीका बताता है किसी एचटीटीपी सोर्स के साथ इंटरैक्ट करने से ठीक पहले हेडर का अनुरोध करें:

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time request headers.
    dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri))
  }

Java

    DataSource.Factory dataSourceFactory =
        new ResolvingDataSource.Factory(
            httpDataSourceFactory,
            // Provide just-in-time request headers.
            dataSpec -> dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)));

आप यह काम करने के लिए ResolvingDataSource का इस्तेमाल भी कर सकते हैं यूआरआई का जस्ट-इन-टाइम संशोधन, जैसा कि नीचे दिए गए स्निपेट में दिखाया गया है:

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time URI resolution logic.
    dataSpec.withUri(resolveUri(dataSpec.uri))
  }

Java

DataSource.Factory dataSourceFactory =
    new ResolvingDataSource.Factory(
        httpDataSourceFactory,
        // Provide just-in-time URI resolution logic.
        dataSpec -> dataSpec.withUri(resolveUri(dataSpec.uri)));

गड़बड़ी ठीक करना पसंद के मुताबिक बनाना

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

Kotlin

val loadErrorHandlingPolicy: LoadErrorHandlingPolicy =
  object : DefaultLoadErrorHandlingPolicy() {
    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
      // Implement custom back-off logic here.
      return 0
    }
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    )
    .build()

Java

LoadErrorHandlingPolicy loadErrorHandlingPolicy =
    new DefaultLoadErrorHandlingPolicy() {
      @Override
      public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
        // Implement custom back-off logic here.
        return 0;
      }
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy))
        .build();

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

डेटा इकट्ठा करने वाले फ़्लैग को पसंद के मुताबिक बनाना

अलग-अलग फ़ॉर्मैट निकालने के तरीके को पसंद के मुताबिक बनाने के लिए, एक्सट्रैक्टर के फ़्लैग का इस्तेमाल किया जा सकता है को ट्रैक किया जा सकता है. इन्हें इस DefaultExtractorsFactory पर सेट किया जा सकता है: DefaultMediaSourceFactory को उपलब्ध कराया गया है. यहां दिए गए उदाहरण में, 14 साल इसकी मदद से MP3 स्ट्रीम के लिए, इंडेक्स पर आधारित वीडियो खोजने की सुविधा चालू की जा सकती है.

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING)
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory))
    .build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING);

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

लगातार बिटरेट में वीडियो चलाने की सुविधा चालू करना

MP3, ADTS, और AMR से स्ट्रीम करने के लिए, किसी FLAG_ENABLE_CONSTANT_BITRATE_SEEKING फ़्लैग के साथ कॉन्सटेंट बिटरेट का अनुमान. डेटा इकट्ठा करने वाले अलग-अलग टूल के लिए, ये फ़्लैग सेट किए जा सकते हैं. इसके लिए, DefaultExtractorsFactory.setXyzExtractorFlags तरीके हैं, जो ऊपर बताए गए हैं. यहां की यात्रा पर हूं डेटा इकट्ठा करने वाले उन सभी टूल के लिए कॉन्स्टेंट बिटरेट की सुविधा चालू करें जो इस पर काम करते हैं. इसके लिए, इसका इस्तेमाल करें DefaultExtractorsFactory.setConstantBitrateSeekingEnabled.

Kotlin

val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);

इसके बाद, DefaultMediaSourceFactory के ज़रिए ExtractorsFactory को इस तरह इंजेक्ट किया जा सकता है: एक्सट्रैक्ट करने वाले फ़्लैग को पसंद के मुताबिक बनाने के बारे में ऊपर बताया गया है.

एसिंक्रोनस बफ़र सूची को चालू करना

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

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

सबसे आसान मामले में, आपकोDefaultRenderersFactory प्लेयर इस तरह से सुनें:

Kotlin

val renderersFactory = 
  DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing()
val exoPlayer = ExoPlayer.Builder(context, renderersFactory).build()

Java

DefaultRenderersFactory renderersFactory =
    new DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing();
ExoPlayer exoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();

अगर आप रेंडरर को सीधे इंस्टैंशिएट कर रहे हैं, तो AsynchronousMediaCodecAdapter.Factory से MediaCodecVideoRenderer और MediaCodecAudioRenderer कंस्ट्रक्टर.

ForwardingPlayer की मदद से कॉल में रुकावट डालना

Player इंस्टेंस के व्यवहार को पसंद के मुताबिक बनाया जा सकता है. इसके लिए, आपको इसे रैप करना होगा इनमें से कोई भी काम करने के लिए, ForwardingPlayer की सब-क्लास और ओवरराइडिंग मेथड का इस्तेमाल निम्न:

  • पैरामीटर को डेलिगेट Player को पास करने से पहले, उन्हें ऐक्सेस करें.
  • उसे लौटाने से पहले प्रतिनिधि Player से उसकी रिटर्न वैल्यू ऐक्सेस करें.
  • इस तरीके को पूरी तरह से फिर से लागू करें.

ForwardingPlayer के तरीकों को ओवरराइड करते समय, पक्का करना ज़रूरी है कि लागू करने की प्रोसेस अपने-आप लागू होती है और Player के मुताबिक होती है इंटरफ़ेस, खास तौर पर ऐसे तरीकों पर काम करता है जिनका मकसद एक जैसा या मिलता-जुलता व्यवहार. उदाहरण के लिए:

  • अगर आपको हर 'गेम' सेटिंग को बदलना है कार्रवाई के लिए, आपको दोनों को ओवरराइड करना होगा ForwardingPlayer.play और ForwardingPlayer.setPlayWhenReady की वजह से कॉलर यह उम्मीद करेगा कि इन तरीकों का व्यवहार एक जैसा होगा, जब playWhenReady = true.
  • आगे-पीछे करने की सीमा में बदलाव करने के लिए, आपको दोनों को बदलना होगा अपने कस्टमाइज़ किए गए वीडियो के साथ वीडियो में आगे/पीछे जाने की सुविधा इस्तेमाल करने के लिए ForwardingPlayer.seekForward और ForwardingPlayer.getSeekForwardIncrement कॉलर के लिए कस्टमाइज़ की गई सही वृद्धि वापस ले सकता है.
  • अगर आपको यह कंट्रोल करना है कि कोई खिलाड़ी, Player.Commands किस तरह का विज्ञापन दिखाए उदाहरण के लिए, आपको Player.getAvailableCommands() और Player.isCommandAvailable(), और यह भी सुनें: इसकी सूचना पाने के लिए, Player.Listener.onAvailableCommandsChanged() कॉलबैक दिए गए प्लेयर की सेटिंग से होने वाले बदलाव दिखेंगे.

MediaSource कस्टमाइज़ेशन

ऊपर दिए गए उदाहरण, सभी वीडियो चलाने के दौरान इस्तेमाल करने के लिए, पसंद के मुताबिक बनाए गए कॉम्पोनेंट इंजेक्ट करते हैं MediaItem ऑब्जेक्ट जो प्लेयर को पास किए जाते हैं. जहां छोटी सी पसंद है इसलिए, ज़रूरत के हिसाब से बदले जा सकने वाले कॉम्पोनेंट को अलग-अलग इंजेक्ट करना भी मुमकिन है MediaSource इंस्टेंस, जिन्हें सीधे प्लेयर को भेजा जा सकता है. उदाहरण के लिए नीचे बताया गया है कि ProgressiveMediaSource को पसंद के मुताबिक कैसे बनाया जा सकता है. DataSource.Factory, ExtractorsFactory, और LoadErrorHandlingPolicy:

Kotlin

val mediaSource =
  ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
    .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
    .createMediaSource(MediaItem.fromUri(streamUri))

Java

ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
        .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
        .createMediaSource(MediaItem.fromUri(streamUri));

कस्टम कॉम्पोनेंट बनाना

लाइब्रेरी में, सबसे ऊपर दिए गए कॉम्पोनेंट को डिफ़ॉल्ट रूप से लागू करने की सुविधा मिलती है इस पेज को पढ़ें. ExoPlayer इन कॉम्पोनेंट का इस्तेमाल कर सकता है, लेकिन कस्टम कार्यान्वयन का उपयोग करने के लिए भी बनाया जा सकता है, यदि गैर-मानक व्यवहार आवश्यक. अपनी ज़रूरत के हिसाब से लागू करने के लिए, इस्तेमाल के कुछ उदाहरण यहां दिए गए हैं:

  • Renderer – हो सकता है कि आप एक कस्टम Renderer लागू करना चाहें मीडिया प्रकार लाइब्रेरी.
  • TrackSelector – पसंद के मुताबिक TrackSelector लागू करने से, ऐप्लिकेशन को मंज़ूरी मिलती है डेवलपर को MediaSource में बिना अनुमति के सार्वजनिक किए गए ट्रैक को इस्तेमाल करने का तरीका बदलना होगा हर उपलब्ध Renderer के हिसाब से इस्तेमाल के लिए चुना गया.
  • LoadControl – पसंद के मुताबिक LoadControl लागू करने से, ऐप्लिकेशन को मंज़ूरी मिलती है डेवलपर को प्लेयर की बफ़रिंग की नीति में बदलाव करना होगा.
  • Extractor – अगर आपको ऐसे कंटेनर फ़ॉर्मैट का इस्तेमाल करना है जो फ़िलहाल उपलब्ध नहीं है अगर लाइब्रेरी का इस्तेमाल किया जा सकता है, तो पसंद के मुताबिक Extractor क्लास लागू करें.
  • MediaSource – कस्टम MediaSource क्लास को लागू करने का तरीका तो तब ठीक होगा, जब आपको किसी रेंडरर में फ़ीड करने के लिए मीडिया के सैंपल चाहिए या अगर आपको कस्टम MediaSource कंपोज़िटिंग लागू करनी है, तो व्यवहार.
  • MediaSource.Factory – पसंद के मुताबिक MediaSource.Factory को लागू करना ऐप्लिकेशन को MediaSource बनाने के तरीके को पसंद के मुताबिक बनाने की अनुमति देता है MediaItem से मिला है.
  • DataSource – ExoPlayer के अपस्ट्रीम पैकेज में पहले से ही कई इस्तेमाल के अलग-अलग उदाहरणों के लिए, DataSource को लागू करना. आप शायद ये करना चाहें डेटा को अन्य तरीके से लोड करने के लिए, अपनी DataSource क्लास लागू करें, जैसे कि एक कस्टम प्रोटोकॉल, जो कस्टम एचटीटीपी स्टैक का इस्तेमाल कर रहा हो या किसी कस्टम स्थायी प्रॉपर्टी से हो कैश मेमोरी.

कस्टम कॉम्पोनेंट बनाते समय, हमारा सुझाव है कि आप ये काम करें:

  • अगर किसी कस्टम कॉम्पोनेंट को इवेंट की शिकायत वापस ऐप्लिकेशन में करनी है, तो हमारा सुझाव है आपको ऐसा करने के लिए, मौजूदा ExoPlayer के कॉम्पोनेंट वाले मॉडल का ही इस्तेमाल करना होगा, उदाहरण के लिए, EventDispatcher क्लास का इस्तेमाल करना या Handler को एक साथ पास करना कॉम्पोनेंट के कंस्ट्रक्टर को सुनने वाला.
  • हमारा सुझाव है कि कस्टम कॉम्पोनेंट और मौजूदा ExoPlayer, दोनों के लिए एक ही मॉडल का इस्तेमाल करें के लिए कॉम्पोनेंट का इस्तेमाल किया जाता है, ताकि वीडियो चलने के दौरान ऐप्लिकेशन को फिर से कॉन्फ़िगरेशन करने की अनुमति मिल सके. ऐसा करने के लिए, कस्टम कॉम्पोनेंट को PlayerMessage.Target लागू करना चाहिए और handleMessage तरीके में कॉन्फ़िगरेशन के बदलाव. ऐप्लिकेशन कोड को यह करना चाहिए ExoPlayer के createMessage तरीके को कॉल करके, कॉन्फ़िगरेशन में बदलाव करें, मैसेज को कॉन्फ़िगर करें और फिर इसका इस्तेमाल करके उसे कॉम्पोनेंट को भेजें PlayerMessage.send. प्लेबैक थ्रेड पर डिलीवर करने के लिए मैसेज भेजे जा रहे हैं यह पक्का करता है कि उन्हें क्रम से लागू किया जाए और इसके लिए कोई अन्य ऑपरेशन प्लेयर पर किया गया.