当媒体项包含多个轨道时,轨道选择是指确定选择哪些轨道进行播放的过程。轨道选择过程由 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,就可以提供 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)。
音频分流 (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());