音轨选择

当媒体项目包含多个轨道时,轨道选择是指确定选择哪些轨道进行播放的过程。轨道选择过程由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查询播放器当前可用的轨道。其次,确定要选择的轨道后,可以使用TrackSelectionOverride将其设置在TrackSelectionParameters上。例如,要从特定的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,适用于大多数用例。它使用Player中设置的TrackSelectionParameters,但也提供一些可以在DefaultTrackSelector.ParametersBuilder中指定的高级自定义选项。

Kotlin

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

Java

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

隧道传输

在渲染器和所选轨道的组合支持的情况下,您可以启用隧道传输播放。为此,请使用DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true)

音频卸载

在渲染器和所选轨道的组合支持的情况下,您可以启用卸载音频播放。为此,请在您的TrackSelectionParameters中指定AudioOffloadModePreferences

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());
);