أخبار المنتجات
تحسين تجربة تشغيل الوسائط: مقدّمة عن ميزة التحميل المُسبَق في Media3 - الجزء 1
قراءة لمدة 8 دقائق
في تطبيقات الوسائط الحالية، يُعدّ توفير تجربة تشغيل سلسة ومتواصلة أمرًا أساسيًا لتقديم تجربة ممتعة للمستخدمين. يتوقّع المستخدمون أن تبدأ فيديوهاتهم على الفور وأن يتم تشغيلها بسلاسة بدون توقّف.
التحدي الأساسي هو وقت الاستجابة. في العادة، لا يبدأ مشغّل الفيديو عمله، أي الربط والتنزيل والتحليل والتخزين المؤقت، إلا بعد أن يختار المستخدم عنصرًا لتشغيله. هذا الأسلوب التفاعلي بطيء في سياق الفيديوهات القصيرة اليوم. الحلّ هو اتّخاذ خطوات استباقية. علينا توقّع المحتوى الذي سيشاهده المستخدم بعد ذلك وتجهيزه مسبقًا. هذه هي فكرة التحميل المُسبَق.
تشمل المزايا الرئيسية للتحميل المُسبَق ما يلي:
- 🚀 بدء التشغيل بشكل أسرع: تكون الفيديوهات جاهزة للتشغيل، ما يؤدي إلى انتقال أسرع بين العناصر وبدء التشغيل بشكل فوري.
- 📉 تقليل التخزين المؤقت: من خلال تحميل البيانات بشكل استباقي، يصبح من غير المرجّح أن يتوقف التشغيل مؤقتًا، مثلاً بسبب مشاكل في الشبكة.
- ✨ تجربة مستخدم أكثر سلاسة: يؤدي الجمع بين سرعة بدء التشغيل وتقليل التخزين المؤقت إلى إنشاء تفاعل أكثر سلاسة يمكن للمستخدمين الاستمتاع به.
في هذه السلسلة المكوّنة من ثلاثة أجزاء، سنقدّم ونشرح بالتفصيل الأدوات المساعدة الفعّالة في Media3 لتحميل المكوّنات (مسبقًا).
- في الجزء 1، سنتناول الأساسيات: فهم استراتيجيات التحميل المُسبَق المختلفة المتوفّرة في Media3، وتفعيل PreloadConfiguration وإعداد DefaultPreloadManager، وإتاحة التحميل المُسبَق للعناصر في تطبيقك. في نهاية هذه المدونة، من المفترض أن تتمكّن من التحميل المُسبَق لعناصر الوسائط وتشغيلها مع الترتيب والمدة المحدّدين.
- في الجزء 2، سنتناول مواضيع أكثر تقدّمًا حول DefaultPreloadManager، مثل استخدام أدوات معالجة الأحداث لإجراء الإحصاءات، واستكشاف أفضل الممارسات الجاهزة للاستخدام في مرحلة الإنتاج، مثل نمط النافذة المنزلقة والمكوّنات المخصّصة المشترَكة في DefaultPreloadManager وExoPlayer.
- في الجزء 3، سنتعمّق في التخزين المؤقت على القرص باستخدام 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 مصمّم خصيصًا للتحميل المُسبَق بشكل استباقي. تدير هذه الفئة مجموعة من مصادر الوسائط المحتملة، وتمنحها الأولوية استنادًا إلى قربها من الموقع الجغرافي الحالي للمستخدم، وتوفّر تحكّمًا دقيقًا في المحتوى الذي سيتم تحميله مسبقًا، ما يجعلها مناسبة لحالات الاستخدام المعقّدة، مثل الخلاصات الديناميكية للفيديوهات القصيرة.
إعداد 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 الذي تعرضه.
على سبيل المثال:
- العنصر "أ" هو الأعلى أولوية، حمِّل 5 ثوانٍ من الفيديو.
- العنصر "ب" له أولوية متوسطة، ولكن عند الوصول إليه، يجب تحميل 3 ثوانٍ من الفيديو.
- العنصر "C" أقل أولوية، ويتم تحميل المسارات فقط.
- العنصر "د" أقل أهمية، لذا عليك الاستعداد له فقط.
- إذا كانت أي عناصر أخرى بعيدة، لا يتم التحميل المُسبَق لأي شيء.
يمكن أن يساعدك هذا التحكّم الدقيق في تحسين استخدام الموارد، وهو أمر يُنصح به لتشغيل المحتوى بسلاسة.
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 للحصول على الرد الذي أعدّه مسبقًا. يمكنك استرداد MediaSource من Preload Manager باستخدام MediaItem.
إذا كان العنصر الذي تم استرجاعه من PreloadManager فارغًا، يعني ذلك أنّه لم يتم التحميل المُسبَق لـ mediaItem بعد أو لم تتم إضافته إلى PreloadMamager، لذا يمكنك اختيار ضبط mediaItem مباشرةً.
// When a media item is about to display 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()
من خلال إعداد MediaSource التي تم استرجاعها من PreloadManager، يمكنك الانتقال بسلاسة من التحميل المُسبَق إلى التشغيل، وذلك باستخدام البيانات المتوفّرة في الذاكرة. وهذا ما يجعل وقت البدء أسرع.
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. إصدار Manager
عندما لا تعود بحاجة إلى PreloadManager (مثلاً، عند إيقاف واجهة المستخدم)، عليك إصداره لإتاحة موارده. يمكنك إجراء ذلك في المكان الذي تتيح فيه موارد "اللاعب". يُنصح بإصدار المدير قبل المشغّل لأنّ المشغّل يمكنه مواصلة التشغيل إذا لم تعُد بحاجة إلى التحميل المُسبَق.
// In your Activity's onDestroy() or Composable's onDispose preloadManager.release()
تقديم العرض التوضيحي
يمكنك الاطّلاع على طريقة استخدام هذه الميزة عمليًا 👍
في العرض التوضيحي أدناه، نرى تأثير PreloadManager على الجانب الأيسر الذي يتميّز بأوقات تحميل أسرع، بينما يعرض الجانب الأيمن التجربة الحالية. يمكنك أيضًا الاطّلاع على نموذج الرمز للعرض التوضيحي. (ميزة إضافية: يعرض أيضًا وقت استجابة بدء التشغيل لكل فيديو)
الخطوات التالية:
هذا كل ما لدينا في الجزء الأول. تتوفّر لديك الآن الأدوات اللازمة لإنشاء نظام تحميل مسبق ديناميكي. يمكنك استخدام PreloadConfiguration لتحميل العنصر التالي في قائمة التشغيل مسبقًا في ExoPlayer أو إعداد DefaultPreloadManager وإضافة العناصر وإزالتها أثناء التنقل وتحديد حالة التحميل المسبق المستهدَفة واسترداد المحتوى المحمَّل مسبقًا بشكل صحيح لتشغيله.
في الجزء 2، سنتعمّق أكثر في DefaultPreloadManager. سنتعرّف على كيفية الاستماع إلى أحداث التحميل المُسبَق، وسنناقش أفضل الممارسات، مثل استخدام نافذة منزلقة لتجنُّب مشاكل الذاكرة، وسنلقي نظرة على المكوّنات المشتركة المخصّصة في ExoPlayer وDefaultPreloadManager.
هل لديك أي ملاحظات تود مشاركتها؟ نتطلّع إلى تلقّي ردّك.
ننصحك بمتابعتنا لمعرفة المزيد قريبًا، ونشجّعك على العمل على تسريع تطبيقك. 🚀
متابعة القراءة
-
أخبار المنتجات
مرحبًا بك في الجزء الثاني من سلسلتنا المكوّنة من ثلاثة أجزاء حول التحميل المُسبَق للوسائط باستخدام Media3. تم تصميم هذه السلسلة لإرشادك خلال عملية إنشاء تجارب وسائط سريعة الاستجابة ومنخفضة وقت الاستجابة في تطبيقات Android.
Mayuri Khinvasara Khabya • مدة القراءة: 9 دقائق
-
أخبار المنتجات
أعلنّا اليوم خلال فعالية The Android Show أنّ نظام التشغيل Android سيتحوّل من نظام تشغيل إلى نظام ذكي، ما يتيح المزيد من فرص التفاعل مع تطبيقاتك.
Matthew McCullough • مدة القراءة: 4 دقائق
-
أخبار المنتجات
تتطوّر المنظومة المتكاملة للأجهزة الجوّالة باستمرار، ما يؤدي إلى ظهور فرص وتهديدات جديدة. من خلال هذه التغييرات، يظلّ Android وGoogle Play ملتزمَين بضمان استمرار إمكانية استفادة مليارات المستخدمين من تطبيقاتهم بثقة وازدهار الابتكار لدى المطوّرين.
Vijaya Kaza • قراءة لمدة 3 دقائق
البقاء على اطّلاع على آخر التحديثات
يمكنك تلقّي أحدث الإحصاءات حول تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.