أخبار المنتجات

‫Media3 1.9.0 - الميزات الجديدة

مدّة القراءة: 6 دقائق
عرض الملف الشخصي لـ Kristina Simakova
Kristina Simakova مدير الهندسة

الإصدار 1.9.0 من Media3 متاح الآن بالإضافة إلى إصلاحات الأخطاء المعتادة وتحسينات الأداء، يتضمّن أحدث إصدار أيضًا أربع وحدات جديدة أو تمت إعادة كتابتها إلى حد كبير:

  • media3-inspector - استخراج البيانات الوصفية والإطارات خارج نطاق التشغيل
  • media3-ui-compose-material3 - إنشاء واجهة مستخدم أساسية لتطبيق وسائط باستخدام Material3 Compose في بضع خطوات فقط
  • media3-cast - التعامل تلقائيًا مع عمليات الانتقال بين البث والتشغيل المحلي
  • ‫media3-decoder-av1: تشغيل فيديوهات AV1 بشكل متسق باستخدام برنامج فك الترميز المعاد كتابته والمستند إلى مكتبة dav1d

أضفنا أيضًا تحسينات على التخزين المؤقت وإدارة الذاكرة في PreloadManager، وقدّمنا العديد من التبسيطات الجديدة في ExoPlayer وTransformer وMediaSession. 

يتيح لك هذا الإصدار أيضًا إمكانية تجريب CompositionPlayer للمرة الأولى لمعاينة تعديلات الوسائط.  


يمكنك مواصلة القراءة لمعرفة المزيد، ويُرجى الاطّلاع دائمًا على ملاحظات الإصدار الكاملة للحصول على نظرة عامة شاملة حول التغييرات في هذا الإصدار.

استخراج البيانات الوصفية والإطارات خارج التشغيل

هناك العديد من الحالات التي تريد فيها فحص الوسائط بدون بدء التشغيل. على سبيل المثال، قد تريد معرفة التنسيقات التي يحتوي عليها أو مدته أو استرداد الصور المصغّرة.

يجمع قسم media3-inspector الجديد كل الأدوات المساعدة لفحص الوسائط بدون تشغيلها في مكان واحد:

  • MetadataRetriever لقراءة المدة والتنسيق والبيانات الوصفية الثابتة من MediaItem
  • FrameExtractor للحصول على لقطات أو صور مصغّرة من ملف
  • MediaExtractorCompat كبديل مباشر لفئة MediaExtractor في نظام Android الأساسي للحصول على معلومات مفصّلة عن العيّنات في الملف

تتّبع MetadataRetriever وFrameExtractor نمطًا بسيطًا AutoCloseable. يمكنك الاطّلاع على صفحات الدليل الجديدة لمزيد من التفاصيل.

suspend fun extractThumbnail(mediaItem: MediaItem) {

  FrameExtractor.Builder(context, mediaItem).build().use {

    val thumbnail = frameExtractor.getThumbnail().await()

  } 

}

إنشاء واجهة مستخدم أساسية لتطبيق وسائط متوافق مع Material3 Compose Media ببضع خطوات

في الإصدارات السابقة، بدأنا في توفير رمز ربط بين عناصر واجهة مستخدم Compose ونسخة Player. في الإصدار 1.9.0 من Media3، أضفنا وحدة جديدة media3-ui-compose-material3 تتضمّن أزرارًا وعناصر محتوى من Material3 مصمَّمة بالكامل. تتيح لك إنشاء واجهة مستخدم للوسائط في بضع خطوات فقط، مع توفير كل المرونة اللازمة لتخصيص النمط. إذا كنت تفضّل إنشاء نمط واجهة المستخدم الخاص بك، يمكنك استخدام وحدات الإنشاء التي تتولّى جميع عمليات التحديث والربط المنطقية، وبالتالي لن تحتاج إلا إلى التركيز على تصميم عنصر في واجهة المستخدم. يُرجى الاطّلاع على صفحات الدليل الموسّع الخاصة بوحدات Compose UI.

نعمل أيضًا على توفير المزيد من مكوّنات Compose، مثل شريط البحث المُنشأ مسبقًا، وبديل كامل وجاهز للاستخدام PlayerView، بالإضافة إلى دمج الترجمة والشرح والإعلانات.

@Composable
fun SimplePlayerUI(player: Player, modifier: Modifier = Modifier) {
  Column(modifier) {
    ContentFrame(player)  // Video surface and shutter logic
    Row (Modifier.align(Alignment.CenterHorizontally)) {                 
      SeekBackButton(player)   // Simple controls
      PlayPauseButton(player)
      SeekForwardButton(player)
    }
  }
}

 

image.png

واجهة مستخدم بسيطة لمشغّل "إنشاء الأغاني" تتضمّن عناصر جاهزة للاستخدام

التعامل تلقائيًا مع عمليات الانتقال بين البث والتشغيل على الجهاز

تمت إعادة كتابة CastPlayer في الوحدة media3-cast للتعامل تلقائيًا مع عمليات الانتقال بين التشغيل المحلي (على سبيل المثال باستخدام ExoPlayer) والتشغيل عن بُعد باستخدام Cast.

عند إعداد MediaSession، ما عليك سوى إنشاء CastPlayer حول ExoPlayer وإضافة MediaRouteButton إلى واجهة المستخدم، وبذلك تكون قد انتهيت.

// MediaSession setup with CastPlayer 

val exoPlayer = ExoPlayer.Builder(context).build()

val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

val session = MediaSession.Builder(context, castPlayer).build()

// MediaRouteButton in UI 

@Composable fun UIWithMediaRouteButton() {

  MediaRouteButton()

}
image.png

دمج CastPlayer الجديد في تطبيق العرض التوضيحي لجلسة Media3

تشغيل فيديوهات AV1 بشكل متسق باستخدام الإضافة المعاد كتابتها استنادًا إلى dav1d

يحتوي الإصدار 1.9.0 على وحدة إضافة AV1 تمت إعادة كتابتها بالكامل استنادًا إلى مكتبة dav1d الشائعة. 

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

دمج التخزين المؤقت وإدارة الذاكرة في PreloadManager

لقد حسّنّا أيضًا PreloadManager. كانت هذه الميزة تتيح لك مسبقًا تحميل الوسائط في الذاكرة خارج نطاق التشغيل ثم تسليمها بسلاسة إلى مشغّل الوسائط عند الحاجة. على الرغم من أنّها كانت تعمل بشكل جيد، كان عليك توخّي الحذر لعدم تجاوز حدود الذاكرة عن طريق التحميل المُسبَق للكثير من البيانات عن طريق الخطأ. لذلك، أضفنا في الإصدار 1.9.0 من Media3 ميزتَين تسهّلان هذه العملية وتجعلانها أكثر استقرارًا:

  1. إتاحة التخزين المؤقت – عند تحديد مدى التحميل المُسبَق، يمكنك الآن اختيار PreloadStatus.specifiedRangeCached(0, 5000) كحالة مستهدَفة للعناصر التي تم تحميلها مُسبقًا. سيؤدي ذلك إلى إضافة النطاق المحدّد إلى ذاكرة التخزين المؤقت على القرص بدلاً من تحميل البيانات إلى الذاكرة. باستخدام هذه الطريقة، يمكنك توفير مجموعة أكبر بكثير من العناصر للتحميل المُسبَق، لأنّ العناصر الأبعد عن العنصر الحالي لم تعُد بحاجة إلى شغل الذاكرة. يُرجى العِلم أنّ ذلك يتطلّب ضبط Cache في DefaultPreloadManager.Builder.
  2. إدارة الذاكرة تلقائيًا – عدّلنا أيضًا واجهة LoadControl للتعامل بشكل أفضل مع حالة التحميل المُسبَق، وبات بإمكانك الآن ضبط حدّ أقصى صريح للذاكرة لجميع العناصر المحمّلة مُسبَقًا في الذاكرة. يبلغ الحدّ الأقصى 144 ميغابايت تلقائيًا، ويمكنك ضبطه في DefaultLoadControl.Builder. سيتوقّف DefaultPreloadManager تلقائيًا عن التحميل المُسبَق عند بلوغ الحدّ الأقصى، وسيحرّر تلقائيًا ذاكرة العناصر ذات الأولوية الأقل إذا لزم الأمر.

الاستفادة من السلوكيات التلقائية الجديدة والمبسّطة في ExoPlayer

وكالعادة، أضفنا أيضًا العديد من التحسينات التدريجية إلى ExoPlayer. في ما يلي بعض الأمثلة:

  • كتم الصوت وإلغاء كتمه: كانت لدينا طريقة setVolume، ولكن أضفنا الآن الطريقتَين mute وunmute لتسهيل استعادة مستوى الصوت السابق بدون الحاجة إلى تذكّره.
  • رصد تعذُّر تشغيل المشغّل: في بعض الحالات النادرة، قد يتعذّر تشغيل المشغّل بسبب مشاكل في برامج الترميز أو إعدادات غير صحيحة، ما يؤدي إلى توقّفه في حالة التخزين المؤقت أو التشغيل بدون إحراز أي تقدّم. سيشعر المستخدمون بالانزعاج، ولكن لن تظهر لك هذه المشاكل في إحصاءاتك. لجعل هذا الأمر أكثر وضوحًا، يعرض المشغّل الآن StuckPlayerException عند رصد حالة تعذُّر التحميل.
  • قفل التنشيط تلقائيًا: كانت إدارة قفل التنشيط تتطلّب الموافقة سابقًا، ما أدّى إلى صعوبة العثور على حالات استخدام نادرة يمكن فيها تأخير تقدّم التشغيل كثيرًا عند التشغيل في الخلفية. أصبحت هذه الميزة اختيارية، لذا لا داعي للقلق بشأنها ويمكنك أيضًا إزالة جميع عمليات معالجة قفل التنشيط اليدوي أثناء التشغيل.
  • إعداد مبسط لمنطق زر الترجمة والشرح – كان من الصعب جدًا تغيير TrackSelectionParameters ليصبح "تفعيل الترجمة والشرح أو إيقافهما"، لذا أضفنا خيارًا بسيطًا من النوع المنطقي selectTextByDefault لحالة الاستخدام هذه.

تبسيط إعدادات أزرار الوسائط المفضّلة في MediaSession

حتى الآن، كان تحديد إعداداتك المفضّلة بشأن الأزرار التي يجب أن تظهر في لوحة الإشعارات الخاصة بالوسائط على Android Auto أو WearOS يتطلّب تحديد الأوامر والأزرار المخصّصة، حتى إذا كنت تريد ببساطة تشغيل طريقة تشغيل عادية.

يتضمّن الإصدار 1.9.0 من Media3 وظيفة جديدة لتسهيل ذلك كثيرًا، إذ يمكنك الآن تحديد إعداداتك المفضّلة لأزرار الوسائط باستخدام أمر مشغّل عادي، بدون الحاجة إلى معالجة الأوامر المخصّصة على الإطلاق.

session.setMediaButtonPreferences(listOf(
    CommandButton.Builder(CommandButton.ICON_FAST_FORWARD) // choose an icon
      .setDisplayName(R.string.skip_forward)
      .setPlayerCommand(Player.COMMAND_SEEK_FORWARD) // choose an action 
      .build()
))
image.png

خيارات زر الوسائط المفضّلة مع زر التقديم السريع

‫CompositionPlayer للمعاينة في الوقت الفعلي

يتضمّن الإصدار 1.9.0 فئة CompositionPlayer ضمن التعليق التوضيحي الجديد @ExperimentalApi. يشير التصنيف إلى أنّ الميزة متاحة للتجربة، ولكنّها لا تزال قيد التطوير. 

‫CompositionPlayer هو مكوّن جديد في واجهات برمجة التطبيقات للتعديل في Media3، وهو مصمَّم لمعاينة تعديلات الوسائط في الوقت الفعلي. استنادًا إلى واجهة Media3 Player المألوفة، تتيح CompositionPlayer للمستخدمين الاطّلاع على التغييرات أثناء تطبيقها قبل بدء عملية التصدير. يستخدم هذا الإجراء عنصر Composition نفسه الذي ستمرّره إلى Transformer للتصدير، ما يؤدي إلى تبسيط سير عمل التعديل من خلال توحيد نموذج البيانات لكلّ من المعاينة والتصدير.

ننصحك بالبدء في استخدام CompositionPlayer ومشاركة ملاحظاتك، كما ننصحك بمتابعة المشاركات والتحديثات القادمة على المستندات للحصول على مزيد من التفاصيل.

‫InAppMuxer كمجمّع تلقائي في Transformer

يستخدم Transformer الآن InAppMp4Muxer كمجمّع تلقائي لكتابة ملفات حاوية الوسائط. داخليًا، تعتمد InAppMp4Muxer على وحدة Muxer في Media3، ما يوفّر سلوكًا متسقًا في جميع إصدارات واجهة برمجة التطبيقات. 

يُرجى العِلم أنّه على الرغم من أنّ Transformer لم يعُد يستخدم MediaMuxer التابع لمنصة Android تلقائيًا، سيظل بإمكانك توفير FrameworkMuxer.Factory من خلال setMuxerFactory إذا كانت حالة الاستخدام تتطلّب ذلك.

واجهات برمجة تطبيقات جديدة لتعديل السرعة

يسهّل الإصدار 1.9.0 استخدام واجهات برمجة التطبيقات الخاصة بتعديل السرعة عند تعديل الوسائط. لقد طرحنا طرقًا جديدة مباشرةً على EditedMediaItem.Builder للتحكّم في السرعة، ما يجعل واجهة برمجة التطبيقات أكثر سهولة في الاستخدام. يمكنك الآن تغيير سرعة مقطع من خلال طلب setSpeed(SpeedProvider provider) على EditedMediaItem.Builder:

val speedProvider = object : SpeedProvider {
    override fun getSpeed(presentationTimeUs: Long): Float {
        return speed
    }

    override fun getNextSpeedChangeTimeUs(timeUs: Long): Long {
        return C.TIME_UNSET
    }
}

EditedMediaItem speedEffectItem = EditedMediaItem.Builder(mediaItem)
    .setSpeed(speedProvider)
    .build()

يحلّ هذا الأسلوب الجديد محلّ الطريقة السابقة التي كانت تستخدم Effects#createExperimentalSpeedChangingEffects()، والتي أوقفناها نهائيًا وستتم إزالتها في إصدار مستقبلي.

التعريف بأنواع المقاطع الصوتية في EditedMediaItemSequence 

في الإصدار 1.9.0، يتطلّب EditedMediaItemSequence تحديد أنواع قنوات الإخراج المطلوبة أثناء إنشاء التسلسل. يضمن هذا التغيير أن يكون التعامل مع المقاطع الصوتية أكثر وضوحًا وقوة في جميع أنحاء "المقطوعة الموسيقية". 

يتم ذلك من خلال أداة إنشاء EditedMediaItemSequence.Builder جديدة تقبل مجموعة من أنواع المسارات (مثل C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO). 

لتبسيط عملية الإنشاء، أضفنا طرقًا ثابتة جديدة لتسهيل الاستخدام:

  • EditedMediaItemSequence.withAudioFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withVideoFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withAudioAndVideoFrom(List<EditedMediaItem>)

ننصحك بنقل البيانات إلى أداة الإنشاء الجديدة أو طرق التسهيل للحصول على تعريفات تسلسلية أكثر وضوحًا وموثوقية.

مثال على إنشاء تسلسل إعلانات فيديو فقط:

EditedMediaItemSequence videoOnlySequence =
    EditedMediaItemSequence.Builder(setOf(C.TRACK_TYPE_VIDEO))
        .addItem(editedMediaItem)
        .build()

يُرجى التواصل معنا من خلال أداة تتبُّع المشاكل في Media3 في حال مواجهة أي أخطاء أو إذا كانت لديك أسئلة أو طلبات ميزات. نتطلّع إلى تلقّي ردّ منك.

متابعة القراءة