اختيار المسار

عندما يحتوي عنصر وسائط على مقاطع صوتية متعددة، فإن اختيار المقطع الصوتي هو العملية التي يحدد الخيار الذي يتم اختياره للتشغيل. تعتمد عملية اختيار المسار تم إعداده بواسطة TrackSelectionParameters، ما يسمح بالعديد من القيود ويلغي التأثير في تحديد المسار المراد تحديده.

الاستعلام عن المسارات المتاحة

يمكنك الاستماع إلى "Player.Listener.onTracksChanged" لتلقّي إشعارات بشأن التغييرات. إلى الأغاني، بما في ذلك:

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

Kotlin

player.addListener(
  object : Player.Listener {
    override fun onTracksChanged(tracks: Tracks) {
      // Update UI using current tracks.
    }
  }
)

Java

player.addListener(
    new Player.Listener() {
      @Override
      public void onTracksChanged(Tracks tracks) {
        // Update UI using current tracks.
      }
    });

يمكنك أيضًا الاستعلام عن المسارات الحالية عن طريق الاتصال بـ player.getCurrentTracks(). تحتوي Tracks المعروضة على قائمة تضم عناصر Track.Group، حيث تظهر المسارات داخل تقدم Group الفردية المحتوى نفسه ولكن بتنسيقات مختلفة.

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

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

يمكن البحث عن كل Group لتحديد قنوات الإصدار المتوافقة مع التشغيل التي يتم اختيارها حاليًا، والمقاطع الصوتية Format التي يستخدمها كل مقطع صوتي:

Kotlin

for (trackGroup in tracks.groups) {
  // Group level information.
  val trackType = trackGroup.type
  val trackInGroupIsSelected = trackGroup.isSelected
  val trackInGroupIsSupported = trackGroup.isSupported
  for (i in 0 until trackGroup.length) {
    // Individual track information.
    val isSupported = trackGroup.isTrackSupported(i)
    val isSelected = trackGroup.isTrackSelected(i)
    val trackFormat = trackGroup.getTrackFormat(i)
  }
}

Java

for (Tracks.Group trackGroup : tracks.getGroups()) {
  // Group level information.
  @C.TrackType int trackType = trackGroup.getType();
  boolean trackInGroupIsSelected = trackGroup.isSelected();
  boolean trackInGroupIsSupported = trackGroup.isSupported();
  for (int i = 0; i < trackGroup.length; i++) {
    // Individual track information.
    boolean isSupported = trackGroup.isTrackSupported(i);
    boolean isSelected = trackGroup.isTrackSelected(i);
    Format trackFormat = trackGroup.getTrackFormat(i);
  }
}

  • يكون المسار متوافقًا إذا كان بإمكان Player فك ترميز وعرض العينات. يُرجى ملاحظة أنّه حتى في حال توفُّر مجموعات تتبُّع متعددة من النوع نفسه (على سبيل المثال: مجموعات مقاطع صوتية متعددة)، فهذا يعني فقط أنها كل على حدة ولا يكون المشغّل بالضرورة قادرًا على تشغيلها في نفس الوقت.
  • يتم اختيار مقطع صوتي إذا تم اختياره لتشغيله استنادًا إلى الوقت الحالي TrackSelectionParameters إذا تم تحديد مقاطع صوتية متعددة ضمن مجموعة مسار واحدة محدد، يستخدم المشغّل المقاطع الصوتية هذه للتشغيل التكيُّفي (على سبيل المثال، مقاطع فيديو متعددة بمعدلات نقل بيانات مختلفة). لاحظ أن واحدة فقط من هذه سيتم تشغيل المقاطع الصوتية في أي وقت.

تعديل معلمات اختيار المسار

يمكن تهيئة عملية اختيار المسار باستخدام Player.setTrackSelectionParameters يمكنك القيام بذلك قبل وأثناء التشغيل. يوضح المثال التالي كيفية الحصول على القيمة الحالية TrackSelectionParameters من المشغِّل، وعدِّلها وعدِّل Player. مع النتيجة المعدلة:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setMaxVideoSizeSd()
    .setPreferredAudioLanguage("hu")
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setMaxVideoSizeSd()
        .setPreferredAudioLanguage("hu")
        .build());

اختيار المقطع الصوتي استنادًا إلى قيود

تتيح لك معظم الخيارات في TrackSelectionParameters تحديد القيود، وتكون مستقلة عن المسارات المتاحة بالفعل. متوفّر تشمل القيود ما يلي:

  • الحد الأقصى والحد الأدنى لعرض الفيديو وارتفاعه وعدد اللقطات في الثانية ومعدل نقل البيانات
  • الحد الأقصى لعدد القنوات الصوتية ومعدل نقل البيانات
  • أنواع بروتوكول MIME المفضّلة للفيديو والصوت
  • لغات الصوت المفضّلة وعلامات الأدوار
  • لغات النص المفضّلة وعلامات الأدوار

يستخدم ExoPlayer إعدادات تلقائية معقولة لهذه القيود، مثل حظر دقة الفيديو على حجم العرض وتفضيل لغة الصوت التي تتطابق مع إعداد لغة نظام المستخدم.

هناك العديد من الفوائد لاستخدام تحديد المسار المستند إلى قيود بدلاً من تحديد مقاطع صوتية محددة من تلك المتاحة:

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

اختيار مقاطع صوتية محددة

من الممكن اختيار مقاطع صوتية معيّنة باستخدام TrackSelectionParameters. أَوَّلًا، يجب البحث عن المسارات المتاحة حاليًا للمشغل باستخدام Player.getCurrentTracks ثانيًا، بعد تحديد المسارات التي يجب تحديدها، يمكن ضبطها على TrackSelectionParameters باستخدام TrackSelectionOverride. على سبيل المثال، لاختيار المقطع الصوتي الأول من audioTrackGroup محدّد:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setOverrideForType(
      TrackSelectionOverride(audioTrackGroup.mediaTrackGroup, /* trackIndex= */ 0)
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setOverrideForType(
            new TrackSelectionOverride(
                audioTrackGroup.getMediaTrackGroup(), /* trackIndex= */ 0))
        .build());

سيتم تطبيق TrackSelectionOverride فقط على ملفات الوسائط التي تحتوي على TrackGroup تطابق تمامًا القيمة المحددة في الإلغاء. وبالتالي لا يمكن تطبيق الإلغاء على عنصر وسائط لاحق إذا كان هذا العنصر يحتوي على مسارات مختلفة.

إيقاف أنواع أو مجموعات الأغاني

يمكن تعطيل أنواع المقاطع الصوتية مثل الفيديو أو الصوت أو النص تمامًا باستخدام TrackSelectionParameters.Builder.setTrackTypeDisabled نوع مسار غير مفعَّل سيتم إيقافه لكل ملفات الوسائط:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
        .build());

بدلاً من ذلك، يمكنك منع اختيار المقاطع الصوتية من مقطع TrackGroup من خلال تحديد إلغاء فارغ لتلك المجموعة:

Kotlin

player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .addOverride(
      TrackSelectionOverride(disabledTrackGroup.mediaTrackGroup, /* trackIndices= */ listOf())
    )
    .build()

Java

player.setTrackSelectionParameters(
    player
        .getTrackSelectionParameters()
        .buildUpon()
        .addOverride(
            new TrackSelectionOverride(
                disabledTrackGroup.getMediaTrackGroup(),
                /* trackIndices= */ ImmutableList.of()))
        .build());

تخصيص أداة اختيار المقاطع الصوتية

تقع مسؤولية اختيار المقطع الصوتي على TrackSelector، وهي مثيل والتي يمكن تقديمها عند إنشاء ExoPlayer والحصول عليها لاحقًا مع ExoPlayer.getTrackSelector().

Kotlin

val trackSelector = DefaultTrackSelector(context)
val player = ExoPlayer.Builder(context).setTrackSelector(trackSelector).build()

Java

DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
ExoPlayer player = new ExoPlayer.Builder(context).setTrackSelector(trackSelector).build();

DefaultTrackSelector هو TrackSelector مرن ومناسب لمعظم الاستخدام. الحالات. ويتم أيضًا استخدام مجموعة TrackSelectionParameters في Player. بعض خيارات التخصيص المتقدمة التي يمكن تحديدها في DefaultTrackSelector.ParametersBuilder:

Kotlin

trackSelector.setParameters(
  trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true))
)

Java

trackSelector.setParameters(
    trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true));

إنشاء نفق

يمكنك تفعيل التشغيل النفقي في الحالات التي تكون فيها مجموعة أجهزة العرض المسارات المحددة يدعم ذلك. للقيام بذلك، استخدم DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true)

نقل الصوت

يمكنك تفعيل خيار تشغيل الصوت غير المثبَّت في الحالات التي يؤدّي فيها إلا أن برامج العرض والمسارات المحددة تتوافق معه. للقيام بذلك، حدد AudioOffloadModePreferences في TrackSelectionParameters.

Kotlin

val audioOffloadPreferences =
  AudioOffloadPreferences.Builder()
      .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
      // Add additional options as needed
      .setIsGaplessSupportRequired(true)
      .build()
player.trackSelectionParameters =
  player.trackSelectionParameters
    .buildUpon()
    .setAudioOffloadPreferences(audioOffloadPreferences)
    .build()

Java

AudioOffloadPreferences audioOffloadPreferences =
  new AudioOffloadPreferences.Builder()
      .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
      // Add additional options as needed
      .setIsGaplessSupportRequired(true)
      .build();
player.setTrackSelectionParameters(
  player.getTrackSelectionParameters()
    .buildUpon()
    .setAudioOffloadPreferences(audioOffloadPreferences)
    .build());
);