يشغّل ExoPlayer معظم أحداث البث المباشر المتكيّف بدون أي إعدادات خاصة. لمزيد من التفاصيل، يُرجى الاطّلاع على صفحة التنسيقات المتوافقة.
توفّر أحداث البث المباشر المتكيّفة نافذة للوسائط المتاحة يتم تعديلها على فترات منتظمة لتتزامن مع الوقت الفعلي الحالي. وهذا يعني أنّ موضع التشغيل سيكون دائمًا في مكان ما ضمن هذه الفترة الزمنية، وفي معظم الحالات، سيكون قريبًا من الوقت الفعلي الحالي الذي يتم فيه إنشاء البث. يُطلق على الفرق بين الوقت الفعلي الحالي وموضع التشغيل اسم الفرق بين الوقت الفعلي ووقت التشغيل.
رصد عمليات التشغيل المباشر ومراقبتها
في كل مرة يتم فيها تعديل نافذة البث المباشر، ستتلقّى مثيلات Player.Listener المسجّلة حدث onTimelineChanged. يمكنك استرداد تفاصيل حول التشغيل المباشر الحالي من خلال طلب البحث باستخدام طرق Player وTimeline.Window المختلفة، كما هو موضّح أدناه وفي الشكل التالي.

- تشير السمة
Player.isCurrentWindowLiveإلى ما إذا كان عنصر الوسائط الذي يتم تشغيله حاليًا هو بث مباشر. تظل هذه القيمة صحيحة حتى إذا انتهى حدث البث المباشر. - يشير
Player.isCurrentWindowDynamicإلى ما إذا كان يتم حاليًا تعديل عنصر الوسائط المشغَّل. وينطبق ذلك عادةً على أحداث البث المباشر التي لم تنتهِ بعد. يُرجى العِلم أنّ هذه العلامة تكون صحيحة أيضًا بالنسبة إلى أحداث البث غير المباشر في بعض الحالات. - تعرض السمة
Player.getCurrentLiveOffsetمقدار الفرق بين الوقت الفعلي الحالي وموضع التشغيل (إذا كان متاحًا). - تعرض السمة
Player.getDurationطول نافذة البث المباشر الحالية. - تعرض
Player.getCurrentPositionموضع التشغيل بالنسبة إلى بداية نافذة البث المباشر. - تعرض الدالة
Player.getCurrentMediaItemعنصر الوسائط الحالي، حيث يحتويMediaItem.liveConfigurationعلى عمليات إلغاء تقدّمها التطبيقات لمعلَمات الإزاحة المباشرة المستهدَفة وتعديل الإزاحة المباشرة. - تعرض الدالة
Player.getCurrentTimelineبنية الوسائط الحالية فيTimeline. يمكن استردادTimeline.Windowالحالي منTimelineباستخدامPlayer.getCurrentMediaItemIndexوTimeline.getWindow. ضمنWindow:- يحتوي
Window.liveConfigurationعلى المَعلمتَين target_live_offset وlive_offset_adjustment. تستند هذه القيم إلى المعلومات الواردة في الوسائط وأي عمليات إلغاء تم ضبطها فيMediaItem.liveConfiguration. -
Window.windowStartTimeMsهو الوقت منذ بداية حقبة Unix الذي تبدأ فيه نافذة البث المباشر. -
Window.getCurrentUnixTimeMsهو الوقت المنقضي منذ بدء حقبة Unix وحتى الوقت الفعلي الحالي. يمكن تصحيح هذه القيمة من خلال فرق زمني معروف بين الخادم والجهاز. Window.getDefaultPositionMsهو الموضع في نافذة البث المباشر الذي سيبدأ المشغّل تشغيله تلقائيًا.
- يحتوي
التقديم والترجيع في أحداث البث المباشر
يمكنك الانتقال إلى أي مكان ضمن نافذة البث المباشر باستخدام Player.seekTo. يكون موضع البحث
الذي تم تمريره مرتبطًا ببداية نافذة البث المباشر. على سبيل المثال، سيؤدي الضغط على seekTo(0) إلى الانتقال إلى بداية نافذة البث المباشر. سيحاول المشغّل الحفاظ على الإزاحة نفسها للبث المباشر كما في الموضع الذي تم الانتقال إليه بعد البحث.
يحتوي نافذة البث المباشر أيضًا على موضع تلقائي من المفترض أن يبدأ التشغيل عنده. يكون هذا الموضع عادةً في مكان قريب من الحافة المباشرة. يمكنك الانتقال إلى الموضع التلقائي من خلال طلب Player.seekToDefaultPosition.
واجهة مستخدم التشغيل المباشر
تعرض مكوّنات واجهة المستخدم التلقائية في ExoPlayer مدة نافذة البث المباشر وموضع التشغيل الحالي ضمنها. وهذا يعني أنّ الموضع سيظهر وكأنّه يتراجع إلى الخلف في كل مرة يتم فيها تعديل نافذة البث المباشر. إذا كنت بحاجة إلى سلوك مختلف، مثلاً عرض وقت Unix أو الإزاحة الحالية للبث المباشر، يمكنك إنشاء نسخة من PlayerControlView وتعديلها لتناسب احتياجاتك.
ضبط معلَمات التشغيل المباشر
يستخدم ExoPlayer بعض المَعلمات للتحكّم في موضع الإزاحة لموضع التشغيل من حافة البث المباشر، ونطاق سرعات التشغيل التي يمكن استخدامها لتعديل موضع الإزاحة هذا.
يحصل ExoPlayer على قيم هذه المَعلمات من ثلاثة مواضع، بترتيب تنازلي حسب الأولوية (يتم استخدام القيمة الأولى التي يتم العثور عليها):
- لكل قيم
MediaItemيتم تمريرها إلىMediaItem.Builder.setLiveConfiguration - تم ضبط القيم التلقائية العامة على
DefaultMediaSourceFactory. - القيم التي تتم قراءتها مباشرةً من الوسائط
Kotlin
// Global settings. val player = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build() // Per MediaItem settings. val mediaItem = MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build() ) .build() player.setMediaItem(mediaItem)
Java
// Global settings. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build(); // Per MediaItem settings. MediaItem mediaItem = new MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()) .build(); player.setMediaItem(mediaItem);
قيم الإعداد المتاحة هي:
-
targetOffsetMs: الإزاحة المستهدَفة للبث المباشر سيحاول المشغّل الاقتراب من هذا الإزاحة المباشرة أثناء التشغيل إذا أمكن ذلك. -
minOffsetMs: الحد الأدنى المسموح به لإزاحة البث المباشر وحتى عند تعديل الإزاحة لتناسب ظروف الشبكة الحالية، لن يحاول المشغّل الحصول على قيمة أقل من هذه الإزاحة أثناء التشغيل. -
maxOffsetMs: الحد الأقصى للإزاحة المباشرة المسموح بها حتى عند ضبط الإزاحة لتناسب ظروف الشبكة الحالية، لن يحاول المشغّل تجاوز هذه الإزاحة أثناء التشغيل. -
minPlaybackSpeed: تمثّل الحد الأدنى لسرعة التشغيل التي يمكن للمشغّل استخدامها كخيار احتياطي عند محاولة الوصول إلى الإزاحة المستهدَفة للبث المباشر. -
maxPlaybackSpeed: تمثّل هذه السمة الحد الأقصى لسرعة التشغيل التي يمكن للمشغّل استخدامها للوصول إلى الإزاحة المستهدَفة للبث المباشر.
تعديل سرعة التشغيل
عند تشغيل بث مباشر بوقت استجابة سريع، يضبط ExoPlayer الإزاحة المباشرة من خلال تغيير سرعة التشغيل بشكل طفيف. سيحاول المشغّل مطابقة الإزاحة المباشرة المستهدَفة التي توفّرها الوسائط أو التطبيق، ولكنّه سيحاول أيضًا الاستجابة لتغيير ظروف الشبكة. على سبيل المثال، إذا حدثت عمليات تخزين مؤقت أثناء التشغيل، سيؤدي ذلك إلى إبطاء التشغيل قليلاً للابتعاد أكثر عن حافة البث المباشر. إذا أصبح الاتصال بالشبكة ثابتًا بما يكفي لتشغيل المحتوى بالقرب من حافة البث المباشر مرة أخرى، سيسرّع المشغّل عملية التشغيل للعودة إلى الإزاحة المستهدَفة للبث المباشر.
إذا لم يكن ضبط سرعة التشغيل تلقائيًا مطلوبًا، يمكن إيقاف هذه الميزة من خلال ضبط القيمتين minPlaybackSpeed وmaxPlaybackSpeed على 1.0f.
وبالمثل، يمكن تفعيلها لأحداث البث المباشر التي لا تتضمّن تأخيرًا منخفضًا من خلال ضبط هذه الإعدادات بشكل صريح على قيم أخرى غير 1.0f. راجِع قسم الإعدادات أعلاه لمعرفة المزيد من التفاصيل حول كيفية ضبط هذه السمات.
تخصيص خوارزمية ضبط سرعة التشغيل
في حال تفعيل ميزة "تعديل السرعة"، يحدّد LivePlaybackSpeedControl التعديلات التي يتم إجراؤها. يمكنك تنفيذ
LivePlaybackSpeedControl مخصّص أو تخصيص التنفيذ التلقائي، وهو
DefaultLivePlaybackSpeedControl. في كلتا الحالتين، يمكن ضبط مثيل عند إنشاء المشغّل:
Kotlin
val player = ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build() ) .build()
Java
ExoPlayer player = new ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( new DefaultLivePlaybackSpeedControl.Builder() .setFallbackMaxPlaybackSpeed(1.04f) .build()) .build();
في ما يلي مَعلمات التخصيص ذات الصلة في DefaultLivePlaybackSpeedControl:
-
fallbackMinPlaybackSpeedوfallbackMaxPlaybackSpeed: الحدّان الأدنى والأقصى لسرعات التشغيل التي يمكن استخدامها للضبط إذا لم يحدّد كل من الوسائط وMediaItemالذي يوفّره التطبيق أي حدود. -
proportionalControlFactor: تتحكّم هذه السمة في مدى سلاسة تعديل السرعة. يؤدي استخدام قيمة عالية إلى جعل التعديلات أكثر مفاجأة وتفاعلية، ولكنها أيضًا أكثر عرضة لأن تكون مسموعة. تؤدي القيمة الأصغر إلى انتقال أكثر سلاسة بين السرعات، ولكنها تكون أبطأ. -
targetLiveOffsetIncrementOnRebufferMs: تتم إضافة هذه القيمة إلى الإزاحة المباشرة المستهدَفة كلما حدثت إعادة تخزين مؤقت، وذلك للمتابعة بحذر أكبر. يمكن إيقاف هذه الميزة من خلال ضبط القيمة على 0. minPossibleLiveOffsetSmoothingFactor: عامل تسوية أسي يُستخدم لتتبُّع الحد الأدنى الممكن لإزاحة البث المباشر استنادًا إلى الوسائط المخزَّنة مؤقتًا حاليًا. تشير القيمة القريبة جدًا من 1 إلى أنّ التقدير أكثر حذرًا وقد يستغرق وقتًا أطول للتكيّف مع تحسّن ظروف الشبكة، بينما تشير القيمة الأقل إلى أنّ التقدير سيتكيّف بشكل أسرع مع ارتفاع خطر مواجهة عمليات تخزين مؤقت.
BehindLiveWindowException وERROR_CODE_BEHIND_LIVE_WINDOW
قد يتأخر موضع التشغيل عن نافذة البث المباشر، مثلاً إذا تم إيقاف المشغّل مؤقتًا أو إذا كان يتم تخزين البيانات مؤقتًا لفترة طويلة بما يكفي. وفي هذه الحالة، سيتعذّر التشغيل وسيتم الإبلاغ عن استثناء برمز الخطأ ERROR_CODE_BEHIND_LIVE_WINDOW من خلال Player.Listener.onPlayerError. قد يرغب رمز التطبيق في معالجة هذه الأخطاء من خلال استئناف التشغيل في الموضع التلقائي. يوضّح PlayerActivity في التطبيق التجريبي هذا الأسلوب.
Kotlin
override fun onPlayerError(error: PlaybackException) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition() player.prepare() } else { // Handle other errors } }
Java
@Override public void onPlayerError(PlaybackException error) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition(); player.prepare(); } else { // Handle other errors } }