当媒体项目包含多个音轨时,音轨选择是确定选择哪些音轨进行播放的过程。音轨选择过程由 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
时提供 TrackSelector
的实例,之后可以使用 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()); );