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

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

قراءة لمدة 6 دقائق
Kristina Simakova
مدير هندسة

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

  • media3-inspector : لاستخراج البيانات الوصفية والإطارات خارج نطاق التشغيل
  • media3-ui-compose-material3 : لإنشاء واجهة مستخدم أساسية للوسائط في Compose مستندة إلى Material3 في بضع خطوات فقط
  • media3-cast : للتعامل تلقائيًا مع عمليات الانتقال بين عمليات التشغيل على 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()

  } 

}

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

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

ما زلنا نعمل أيضًا على إضافة المزيد من مكوّنات 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

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

التعامل تلقائيًا مع عمليات الانتقال بين عمليات التشغيل على Cast وعمليات التشغيل المحلية

تمت إعادة كتابة 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 session التجريبي

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

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

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

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

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

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

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

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

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

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

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

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

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 مصمّم لمعاينة تعديلات الوسائط في الوقت الفعلي. استنادًا إلى واجهة Player المألوفة في Media3، يتيح 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 تحديد أنواع مسارات الإخراج المطلوبة أثناء إنشاء التسلسل. يضمن هذا التغيير أن يكون التعامل مع المسارات أكثر وضوحًا وثباتًا في جميع أنحاء Composition. 

يتم ذلك من خلال أداة إنشاء 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 إذا واجهت أي أخطاء أو إذا كانت لديك أسئلة أو طلبات ميزات. يسرّنا سماع رأيك.

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