اخبار محصول

افزایش کیفیت پخش رسانه: معرفی پیش‌بارگذاری با Media3 - بخش 1

۸ دقیقه مطالعه
Mayuri Khinvasara Khabya
مهندس روابط توسعه‌دهنده

در برنامه‌های رسانه‌ای امروزی، ارائه یک تجربه پخش روان و بدون وقفه، کلید یک تجربه کاربری لذت‌بخش است. کاربران انتظار دارند ویدیوهایشان فوراً شروع شوند و بدون مکث و به طور یکپارچه پخش شوند.

چالش اصلی، تأخیر است. به طور سنتی، یک پخش‌کننده ویدیو فقط پس از انتخاب یک آیتم توسط کاربر برای پخش، کار خود - اتصال، دانلود، تجزیه، بافر - را آغاز می‌کند. این رویکرد واکنشی برای محتوای ویدیوی کوتاه امروزی کند است. راه حل، پیشگیرانه بودن است. ما باید پیش‌بینی کنیم که کاربر در مرحله بعد چه چیزی را تماشا خواهد کرد و محتوا را از قبل آماده کنیم. این جوهره پیش‌بارگذاری است.

مزایای کلیدی پیش بارگذاری عبارتند از:

  • 🚀 شروع پخش سریع‌تر: ویدیوها از قبل آماده پخش هستند که منجر به انتقال سریع‌تر بین موارد و شروع فوری‌تر می‌شود.
  • 📉 کاهش حجم بافر: با بارگذاری پیشگیرانه داده‌ها، احتمال توقف پخش، مثلاً به دلیل قطعی شبکه، بسیار کمتر می‌شود.
  • ✨ نتیجه‌ی تجربه‌ی کاربری روان‌تر: ترکیب شروع سریع‌تر و بافر کمتر، تعاملی روان‌تر و یکپارچه‌تر را برای کاربران ایجاد می‌کند تا از آن لذت ببرند.

در این مجموعه سه قسمتی، ابزارهای قدرتمند Media3 برای (پیش)بارگذاری اجزا را معرفی و بررسی عمیق خواهیم کرد.

  • در بخش اول، مبانی را پوشش خواهیم داد: درک استراتژی‌های مختلف پیش‌بارگذاری موجود در Media3، فعال کردن PreloadConfiguration و تنظیم DefaultPreloadManager، که به برنامه شما امکان می‌دهد موارد را از قبل بارگذاری کند. در پایان این وبلاگ، شما باید بتوانید موارد رسانه‌ای را با رتبه‌بندی و مدت زمان پیکربندی شده خود از قبل بارگذاری و پخش کنید.
  • در بخش دوم ، به مباحث پیشرفته‌تر DefaultPreloadManager خواهیم پرداخت: استفاده از شنونده‌ها برای تجزیه و تحلیل، بررسی بهترین شیوه‌های آماده برای تولید مانند الگوی پنجره کشویی و اجزای مشترک سفارشی DefaultPreloadManager و ExoPlayer.
  • در بخش سوم، به طور عمیق به بررسی ذخیره‌سازی دیسک با استفاده از DefaultPreloadManager خواهیم پرداخت.

پیش‌دانلود به کمک می‌آید! 🦸‍♀️

ایده اصلی پشت پیش‌بارگذاری ساده است: محتوای رسانه را قبل از نیاز بارگیری کنید. زمانی که کاربر به ویدیوی بعدی می‌رود، بخش‌های اول ویدیو از قبل دانلود شده و در دسترس هستند و آماده پخش فوری می‌باشند.

مثل یک رستوران به آن فکر کنید. یک آشپزخانه شلوغ منتظر دستور برای شروع خرد کردن پیاز نمی‌ماند. 🧅 آنها کارهای آماده‌سازی خود را از قبل انجام می‌دهند. پیش‌بارگذاری، کار آماده‌سازی برای پخش‌کننده ویدیوی شماست.

وقتی این قابلیت فعال باشد، پیش‌بارگذاری می‌تواند به حداقل رساندن تأخیر اتصال کمک کند، زمانی که کاربر قبل از رسیدن بافر پخش به مورد بعدی، به مورد بعدی می‌رود. دوره اول پنجره بعدی آماده می‌شود و نمونه‌های ویدیویی، صوتی و متنی بافر می‌شوند. دوره پیش‌بارگذاری شده بعداً در صف پخش قرار می‌گیرد و نمونه‌های بافر شده بلافاصله در دسترس هستند و آماده ارسال به کدک برای رندر شدن می‌باشند.

در Media3 دو API اصلی برای پیش‌بارگذاری وجود دارد که هر کدام برای موارد استفاده‌ی متفاوتی مناسب هستند. انتخاب API مناسب اولین قدم است.

۱. پیش بارگذاری آیتم‌های لیست پخش با PreloadConfiguration

این رویکرد ساده‌ای است و برای رسانه‌های خطی و متوالی مانند لیست‌های پخش که ترتیب پخش آنها قابل پیش‌بینی است (مانند یک سری قسمت) مفید است. شما لیست کامل موارد رسانه‌ای را با استفاده از APIهای لیست پخش ExoPlayer به پخش‌کننده می‌دهید و PreloadConfiguration را برای پخش‌کننده تنظیم می‌کنید، سپس پخش‌کننده به طور خودکار موارد بعدی را در دنباله، همانطور که پیکربندی شده است، از قبل بارگیری می‌کند. این API تلاش می‌کند تا تأخیر اتصال را هنگامی که کاربر قبل از همپوشانی بافر پخش با مورد بعدی، به مورد بعدی می‌رود، بهینه کند.

پیش‌بارگذاری فقط زمانی شروع می‌شود که هیچ رسانه‌ای برای پخش مداوم بارگیری نشده باشد، که این امر مانع از رقابت آن برای پهنای باند با پخش اولیه می‌شود.

اگر هنوز مطمئن نیستید که آیا به پیش‌بارگذاری نیاز دارید یا خیر، این API یک گزینه عالی و کم‌هزینه برای امتحان کردن است!

  player.preloadConfiguration =
    PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)

با استفاده از PreloadConfiguration بالا، پخش‌کننده سعی می‌کند پنج ثانیه از رسانه را برای مورد بعدی در لیست پخش از قبل بارگذاری کند.

پس از انتخاب، می‌توان پیش‌بارگذاری لیست پخش را با استفاده از PreloadConfiguration.DEFAULT برای غیرفعال کردن پیش‌بارگذاری لیست پخش، دوباره غیرفعال کرد:

  player.preloadConfiguration = PreloadConfiguration.DEFAULT

۲. پیش بارگذاری لیست‌های پویا با PreloadManager

برای رابط‌های کاربری پویا مانند فیدهای عمودی یا چرخ و فلک‌ها، که در آن‌ها مورد "بعدی" توسط تعامل کاربر تعیین می‌شود، API PreloadManager مناسب است. این یک کامپوننت جدید، قدرتمند و مستقل در کتابخانه Media3 ExoPlayer است که به طور خاص برای پیش‌بارگذاری فعال طراحی شده است. این API مجموعه‌ای از MediaSourceهای بالقوه را مدیریت می‌کند، آن‌ها را بر اساس نزدیکی به موقعیت فعلی کاربر اولویت‌بندی می‌کند و کنترل دقیقی بر آنچه که باید پیش‌بارگذاری شود، ارائه می‌دهد که برای سناریوهای پیچیده مانند فیدهای پویا از ویدیوهای کوتاه مناسب است.

تنظیم PreloadManager

DefaultPreloadManager پیاده‌سازی استاندارد PreloadManager است.

سازنده‌ی DefaultPreloadManager می‌تواند هم DefaultPreloadManager و هم هر نمونه‌ی ExoPlayer که محتوای از پیش بارگذاری شده‌ی آن را پخش می‌کند، بسازد. برای ایجاد یک DefaultPreloadManager، باید یک TargetPreloadStatusControl ارسال کنید که مدیر preload می‌تواند با پرس‌وجو از آن، میزان بارگذاری یک آیتم را تعیین کند. در بخش زیر، مثالی از TargetPreloadStatusControl را توضیح داده و تعریف خواهیم کرد.

  val preloadManagerBuilder =
DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = val preloadManagerBuilder.build()

// Build ExoPlayer with DefaultPreloadManager.Builder
val player = preloadManagerBuilder.buildExoPlayer()

استفاده از سازنده یکسان برای ExoPlayer و DefaultPreloadManager ضروری است، که تضمین می‌کند اجزای زیر مجموعه آنها به درستی به اشتراک گذاشته شوند.

و تمام! حالا شما یک مدیر دارید که آماده دریافت دستورالعمل‌ها است.

پیکربندی مدت زمان و رتبه‌بندی با TargetPreloadStatusControl

اگر بخواهید مثلاً ۱۰ ثانیه ویدیو را از قبل بارگذاری کنید، چه؟ می‌توانید موقعیت آیتم‌های رسانه‌ای خود را در چرخ و فلک مشخص کنید و DefaultPreloadManager بارگذاری آیتم‌ها را بر اساس میزان نزدیکی آنها به آیتمی که کاربر در حال پخش آن است، اولویت‌بندی می‌کند.

اگر می‌خواهید مدت زمان پیش‌بارگذاری آیتم را کنترل کنید، می‌توانید با استفاده از DefaultPreloadManager.PreloadStatus آن را تعیین کنید.

برای مثال،

  • مورد «الف» بالاترین اولویت را دارد، ۵ ثانیه ویدیو را بارگذاری می‌کند.
  • مورد «ب» اولویت متوسطی دارد، اما وقتی به آن رسیدید، ۳ ثانیه ویدیو را بارگذاری کنید.
  • مورد «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 یک مکالمه مبتنی بر وضعیت بین رابط کاربری شما و موتور پیش‌بارگذاری است.

۱. افزودن موارد رسانه‌ای

همزمان با پر کردن فید خود، باید مدیر را از رسانه‌هایی که باید ردیابی شوند مطلع کنید. اگر شروع می‌کنید، می‌توانید کل لیستی را که می‌خواهید پیش‌بارگذاری کنید، اضافه کنید. متعاقباً می‌توانید در صورت نیاز، یک مورد را به لیست اضافه کنید. شما کنترل کاملی بر روی موارد موجود در لیست پیش‌بارگذاری دارید، به این معنی که باید آنچه را که از مدیر اضافه و حذف می‌شود نیز مدیریت کنید.

  val initialMediaItems = pullMediaItemsFromService(/* count= */ 20)
for (index in 0 until initialMediaItems.size) {
    preloadManager.add(
        initialMediaItems.get(index),index)
    )
}

مدیر اکنون شروع به دریافت داده‌ها برای این MediaItem در پس‌زمینه خواهد کرد.

پس از افزودن، به مدیر بگویید که لیست جدید خود را دوباره ارزیابی کند (اشاره به اینکه چیزی تغییر کرده است مانند اضافه کردن/حذف یک مورد، یا اینکه کاربر برای پخش یک مورد جدید سوئیچ می‌کند.)

  preloadManager.invalidate()

۲. بازیابی و پخش یک آیتم

منطق اصلی پخش اینجاست. وقتی کاربر تصمیم به پخش آن ویدیو می‌گیرد، نیازی به ایجاد یک MediaSource جدید ندارید. در عوض، از PreloadManager درخواست می‌کنید که آن را از قبل آماده کرده است. می‌توانید MediaSource را از Preload Manager با استفاده از MediaItem بازیابی کنید.

اگر آیتم بازیابی شده از PreloadManager تهی (null) باشد، به این معنی است که 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()

با آماده‌سازی MediaSource بازیابی‌شده از PreloadManager، شما می‌توانید با استفاده از داده‌های موجود در حافظه، به طور یکپارچه از پیش‌بارگذاری به پخش منتقل شوید. این همان چیزی است که زمان شروع را سریع‌تر می‌کند.

۳. شاخص فعلی را با رابط کاربری همگام نگه دارید

از آنجایی که فید/لیست ما می‌تواند پویا باشد، مهم است که PreloadManager را از فهرست پخش فعلی خود مطلع کنید تا همیشه بتواند موارد نزدیک به فهرست فعلی شما را برای پیش‌بارگذاری در اولویت قرار دهد.

  preloadManager.setCurrentPlayingIndex(currentIndex)
// Need to call invalidate() to update the priorities
preloadManager.invalidate()

۴. حذف یک آیتم

برای حفظ کارایی مدیر، باید مواردی را که دیگر نیازی به ردیابی آنها نیست، مانند مواردی که از موقعیت فعلی کاربر دور هستند، حذف کنید.

  // When an item is too far from the current playing index
preloadManager.remove(mediaItem)

اگر نیاز دارید که همه موارد را به طور همزمان پاک کنید، می‌توانید preloadManager.reset() را فراخوانی کنید.

۵. مدیر را آزاد کنید

وقتی دیگر به PreloadManager نیازی ندارید (مثلاً وقتی رابط کاربری شما از بین می‌رود)، باید آن را رها کنید تا منابعش آزاد شوند. یک جای خوب برای انجام این کار جایی است که منابع بازیکن خود را آزاد کرده‌اید. توصیه می‌شود مدیر را قبل از بازیکن آزاد کنید زیرا اگر نیازی به پیش‌بارگذاری بیشتر نداشته باشید، بازیکن می‌تواند به بازی ادامه دهد.

  // In your Activity's onDestroy() or Composable's onDispose
preloadManager.release()

زمان نسخه آزمایشی

به صورت زنده و در عمل ببینید 👍

در دموی زیر، تأثیر PreloadManager را در سمت راست می‌بینیم که زمان بارگذاری سریع‌تری دارد، در حالی که سمت چپ تجربه فعلی را نشان می‌دهد. همچنین می‌توانید نمونه کد دمو را مشاهده کنید. (نکته مثبت: همچنین تأخیر راه‌اندازی را برای هر ویدیو نمایش می‌دهد)

نسخه آزمایشی-مدیریت پیش‌بارگذاری_2.webp

قدم بعدی چیست؟

و این هم از بخش اول! اکنون ابزارهای لازم برای ساخت یک سیستم پیش‌بارگذاری پویا را دارید. می‌توانید از PreloadConfiguration برای پیش‌بارگذاری آیتم بعدی یک لیست پخش در ExoPlayer استفاده کنید یا یک DefaultPreloadManager راه‌اندازی کنید، آیتم‌ها را درجا اضافه و حذف کنید، وضعیت پیش‌بارگذاری هدف را پیکربندی کنید و محتوای پیش‌بارگذاری شده را برای پخش به درستی بازیابی کنید.

در بخش دوم ، عمیق‌تر به DefaultPreloadManager خواهیم پرداخت. نحوه‌ی گوش دادن به رویدادهای پیش‌بارگذاری را بررسی خواهیم کرد، در مورد بهترین شیوه‌ها مانند استفاده از یک پنجره‌ی کشویی برای جلوگیری از مشکلات حافظه بحث خواهیم کرد و نگاهی اجمالی به اجزای مشترک سفارشی ExoPlayer و DefaultPreloadManager خواهیم داشت.

آیا نظری برای به اشتراک گذاشتن دارید؟ ما مشتاق شنیدن نظرات شما هستیم.

با ما همراه باشید و برنامه‌تان را سریع‌تر کنید! 🚀

    نوشته شده توسط:

    ادامه مطلب