حِزم الشبكة

يُستخدَم ExoPlayer بشكل شائع لبث الوسائط عبر الإنترنت. وهي تدعم حزم شبكات متعددة لإجراء طلبات الشبكة الأساسية. يمكن أن يؤثر اختيارك لنظام الحِزم في الشبكة بشكل كبير في أداء البث.

توضّح هذه الصفحة كيفية ضبط ExoPlayer لاستخدام حِزمة الشبكة التي تريدها، وتُدرج الخيارات المتاحة، وتقدّم بعض الإرشادات حول كيفية اختيار حِزمة شبكة لتطبيقك، وتوضّح كيفية تفعيل ميزة التخزين المؤقت للوسائط التي يتم بثها.

إعداد ExoPlayer لاستخدام حزمة شبكة محدّدة

يحمّل ExoPlayer البيانات من خلال مكوّنات DataSource التي يحصل عليها من تم إدخال DataSource.Factory مثيل من رمز التطبيق.

إذا كان تطبيقك يحتاج إلى تشغيل محتوى http(s) فقط، يُرجى اختيار شبكة. يمكن بسهولة تحديث أي مثيلات DataSource.Factory التي حقن التطبيق ليكون مثيلاً لـ HttpDataSource.Factory الذي يتجاوب مع مكدس الشبكة الذي ترغب في استخدامه. إذا كان تطبيقك يحتاج أيضًا إلى تشغيل محتوى غير http(s)، مثل الملفات المحلية، استخدِم DefaultDataSource.Factory:

Kotlin

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

Java

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

في هذا المثال، PreferredHttpDataSource.Factory هو المصنع المقابل لسلسلة حزم الشبكة المفضّلة لديك. تمنح طبقة DefaultDataSource.Factory الدعم للمصادر التي ليست http(s) مثل الملفات المحلية.

يوضّح المثال التالي كيفية إنشاء 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 داخليًا، دعم HTTP وHTTP/2 وHTTP/3 عبر بروتوكولات QUIC.

يدعم ExoPlayer استخدام HttpEngine مع HttpEngineDataSource.Factory. يمكنك إدراج مصنع مصادر البيانات هذا كما هو موضّح في مقالة ضبط ExoPlayer لاستخدام ملف برمجي محدد لبروتوكول الإنترنت.

Cronet

Cronet هي تم توفير حزمة شبكة Chromium لتطبيقات Android كمكتبة. يستفيد Cronet من تقنيات متعدّدة تقلّل من وقت الاستجابة وتزيد من معدل نقل البيانات لطلبات الشبكة التي يحتاج تطبيقك إلى تنفيذها، بما في ذلك تلك التي أنشأها ExoPlayer. وهو يدعم في الأصل HTTP وHTTP/2 وHTTP/3 عبر QUIC والبروتوكولات. يستخدم بعض أكبر تطبيقات البث في العالم مكتبة Cronet، بما في ذلك YouTube.

يتوافق ExoPlayer مع Cronet من خلال مكتبة Cronet. اطّلِع على README.md المكتبة للحصول على تعليمات مفصّلة حول كيفية استخدام هذه الميزة. يُرجى العِلم أنّ مكتبة Cronet يمكنها استخدام ثلاثة تطبيقات لـ Cronet الأساسية:

  1. خدمات Google Play: ننصح باستخدام طريقة التنفيذ هذه في معظم وحالات استخدام حزمة الشبكة المدمَجة في Android (DefaultHttpDataSource) إذا لم تكن "خدمات Google Play" متاحة.
  2. مكتبة Cronet المضمّنة: قد تكون خيارًا جيدًا إذا كانت نسبة كبيرة من المستخدمين تقيم في أسواق لا تتوفّر فيها "خدمات Google Play" على نطاق واسع، أو إذا كنت تريد التحكّم في الإصدار الدقيق لتنفيذ Cronet المستخدَم. تشير رسالة الأشكال البيانية من العيب الرئيسي في Cronet inline هو أنه يضيف حوالي 8 ميغابايت إلى تطبيقك.
  3. الطريقة الاحتياطية لاستخدام Cronet: تُنفِّذ الطريقة الاحتياطية لاستخدام Cronet واجهة برمجة التطبيقات الخاصة بخدمة Cronet كحزمة حول حِزمة الشبكة المضمّنة في Android. يجب لا يتم استخدامها مع ExoPlayer، نظرًا لأن استخدام حزمة الشبكة المدمجة في Android مباشرةً (باستخدام DefaultHttpDataSource) أكثر كفاءة.

OkHttp

OkHttp هو حزمة أخرى حديثة للشبكة يتم استخدامها على نطاق واسع من قِبل العديد من تطبيقات Android الشائعة. وهو متوافق مع HTTP و HTTP/2، ولكنّه لا يتوافق بعد مع HTTP/3 عبر QUIC.

يتوافق ExoPlayer مع OkHttp من خلال مكتبة OkHttp. اطّلِع على README.md المكتبة للحصول على تعليمات مفصّلة حول كيفية استخدام هذه الميزة. عند استخدام مكتبة OkHttp، يتم تضمين مكدس الشبكة داخل التطبيق. وهو مشابه لـ Cronet Include، إلّا أن OkHttp تعتمد بشكل كبير على أصغر، مع إضافة أقل من 1 ميغابايت إلى التطبيق.

حزمة الشبكة المدمجة في Android

يتيح ExoPlayer استخدام حزمة الشبكة المدمجة في Android مع DefaultHttpDataSource وDefaultHttpDataSource.Factory، وهما جزء من مكتبة ExoPlayer الأساسية.

يعتمد التنفيذ الدقيق لحزمة بروتوكول الإنترنت على البرنامج الذي يعمل على الجهاز الأساسي. على معظم الأجهزة، لا يتوفّر سوى بروتوكول HTTP (أي أنّ بروتوكولَي HTTP/2 وHTTP/3 عبر QUIC غير متاحَين).

حزم الشبكات الأخرى

ويمكن للتطبيقات أيضًا دمج حزم شبكات أخرى مع ExoPlayer. لإجراء ذلك، يجب تنفيذ HttpDataSource الذي يلتفّ حزمة الشبكة. مع HttpDataSource.Factory مطابق. وتعد مكتبتا Cronet و OkHttp في ExoPlayer مثالَين جيدَين على كيفية إجراء ذلك.

عند الدمج مع مكدس شبكة Java خالص، من الأفضل تنفيذ DataSourceContractTest للتحقّق من أنّ عملية تنفيذ HttpDataSource يتصرف بشكل صحيح. يُعدّ OkHttpDataSourceContractTest في مكتبة OkHttp مثالاً جيدًا على كيفية تنفيذ ذلك.

اختيار تكديس شبكة

يوضّح الجدول التالي إيجابيات وسلبيات حِزم الشبكة المتوافقة مع ExoPlayer.

حزم الشبكات البروتوكولات تأثير حجم حزمة APK ملاحظات
محرّك HttpEngine بروتوكول HTTP
HTTP/2
HTTP/3 عبر QUIC
بدون تحديد نمط لا تتوفّر إلا في واجهة برمجة التطبيقات 34 أو S Extensions 7
Cronet (خدمات Google Play) HTTP
HTTP/2
HTTP/3 عبر QUIC
صغيرة
(<100 كيلوبايت)
يجب استخدام خدمات Google Play. تم تعديل إصدار Cronet تلقائيًا
Cronet (مضمّن) بروتوكول HTTP
HTTP/2
HTTP/3 عبر QUIC
كبير
(حوالي 8 ميغابايت)
إصدار Cronet الذي يتحكّم فيه مطوِّر التطبيقات
Cronet (العنصر الاحتياطي) HTTP
(يختلف حسب الجهاز)
صغيرة
(<100 كيلوبايت)
لا يُنصح باستخدام هذا الإعداد مع ExoPlayer.
OkHttp HTTP
HTTP/2
صغيرة
(<1 ميغابايت)
حِزم الشبكات المدمَجة HTTP
(يختلف حسب الجهاز)
بدون تحديد نمط تختلف خطوات التنفيذ حسب الجهاز.

يمكن لبروتوكول HTTP/2 وHTTP/3 عبر بروتوكولات QUIC تحسين الوسائط بشكل كبير. أداء البث. وعلى وجه الخصوص، عند بث الوسائط التكيُّفية ذات باستخدام شبكة توزيع المحتوى (CDN)، فهناك حالات التي تتيح استخدام هذه البروتوكولات لشبكات توصيل المحتوى (CDN) بالعمل بكفاءة أكبر. لهذا السبب، فإنّ توافق HttpEngine وCronet مع كل من HTTP/2 وHTTP/3 على QUIC (وتوافق OkHttp مع HTTP/2) يشكّل ميزة كبيرة مقارنةً باستخدام حِزمة الشبكة المضمّنة في Android، شرط أن تكون الخوادم التي يتم عليها استضافة المحتوى متوافقة أيضًا مع هذه البروتوكولات.

عند التفكير في بث الوسائط بشكل منفصل، نوصي باستخدام HttpEngine أو إصدار Cronet المقدَّم من "خدمات Google Play" بدءًا من DefaultHttpDataSource إذا كانت "خدمات Google Play" غير متاحة يحقق هذا الاقتراح فائدة التوازن بين تفعيل استخدام HTTP/2 وHTTP/3 عبر QUIC على معظم الأجهزة، مع تجنُّب حدوث زيادة كبيرة في حجم حِزم APK. هناك استثناءات لهذا الاقتراح. في الحالات التي يُحتمل فيها عدم توفّر "خدمات Google Play" على نسبة كبيرة من الأجهزة التي سيتم تشغيل تطبيقك عليها، قد يكون استخدام 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();