当媒体内容包含多个轨道时,轨道选择是指确定要播放哪个轨道的过程。轨道选择过程由 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
包含 Tracks.Group
对象列表,其中单个 Group
中的轨道显示相同的内容,但格式不同。
下面举例说明了如何对轨道进行分组。假设您采用了自适应播放,主视频画面以 5 种比特率提供,备用视频画面(例如体育赛事中的不同摄像机角度)以 2 种比特率提供。在本例中,将有两个视频轨道组,一个对应于包含 5 个轨道的视频主 Feed,另一个对应于包含 2 个轨道的备用视频 Feed。
不同语言的音轨不会归为一组,因为不同语言的内容不被视为相同。反之,如果音轨使用相同的语言,但仅在比特率、采样率、声道数等属性方面存在差异,则可以归为一组。这也适用于文字轨道。
您可以查询每个 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
完全匹配的 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)
。
音频分流 (offload)
如果渲染程序和所选轨道的组合支持,您可以启用分流音频播放。为此,请在 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()); );