当媒体项包含多个轨道时,轨道选择就是
来决定选择哪个文件进行播放轨道选择流程
由 TrackSelectionParameters
配置,以允许许多不同的
用于影响要指定的轨道选择。
查询可用轨道
您可以监听Player.Listener.onTracksChanged
,以便在有更改时收到通知
包括:
- 在准备媒体项时了解可用的轨道 完整播放次数。请注意,播放器需要准备一个媒体项 其中包含哪些曲目
- 播放模式从一种媒体播放时,可用曲目会发生变化 复制到另一个对象
- 对所选轨道的更改。
player.addListener(
object : Player.Listener {
override fun onTracksChanged(tracks: Tracks) {
// Update UI using current tracks.
}
}
)
player.addListener(
new Player.Listener() {
@Override
public void onTracksChanged(Tracks tracks) {
// Update UI using current tracks.
}
});
您还可以通过调用 player.getCurrentTracks()
查询当前轨道。
返回的 Tracks
包含 Track.Group
对象列表,其中
单个 Group
以不同的格式呈现相同的内容。
下面举例说明如何对曲目进行分组,我们以自适应播放为例, 一个主视频 Feed 有五种比特率,另一个视频 Feed (例如,体育比赛中的不同镜头角度)以两种比特率提供。 在本示例中,将有两个视频轨道组,一个对应于主视频轨道 包含 5 首曲目的视频 Feed,另有 1 秒的备用视频 Feed 包含两个轨道
由于语言不同的音轨内容 语言并不相同。相反,音轨 只不过在比特率、采样等属性方面存在差异 速率、通道数等都可以分组这也适用于文本轨道。
可以查询每个 Group
,以确定支持哪些轨道
播放,当前所选的曲目,以及每首曲目使用的 Format
:
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)
}
}
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
替换为修改后的结果:
player.trackSelectionParameters =
player.trackSelectionParameters
.buildUpon()
.setMaxVideoSizeSd()
.setPreferredAudioLanguage("hu")
.build()
player.setTrackSelectionParameters(
player
.getTrackSelectionParameters()
.buildUpon()
.setMaxVideoSizeSd()
.setPreferredAudioLanguage("hu")
.build());
基于约束条件的轨道选择
TrackSelectionParameters
中的大多数选项都允许您指定约束条件,
这些轨道与实际可用的轨道无关可用
限制包括:
- 最大和最小视频宽度、高度、帧速率和比特率。
- 最大音频声道数量和比特率。
- 视频和音频的首选 MIME 类型。
- 首选音频语言和角色标志。
- 首选文本语言和角色标志。
ExoPlayer 会针对这些限制使用合理的默认值,例如 与显示器尺寸调整视频分辨率,并优先选择 与用户的系统语言区域设置一致。
与使用基于约束条件的轨道选择相比有几个好处 从现有的曲目中选择特定的曲目:
- 您可以在了解媒体项提供的跟踪内容之前指定限制条件。 这意味着,可以在播放器准备好 媒体项,而选择特定轨道需要应用代码 等到已知可用轨道。
- 限制条件会应用于播放列表中的所有媒体项,即使
项具有不同的可用轨道。例如,首选音频语言
限制条件将自动应用于所有媒体项,即使
该语言的曲目
Format
因媒体项而异。 如下所述,选择特定轨道时并不会出现这种情况。
选择特定轨道
您可以使用 TrackSelectionParameters
选择特定轨道。首先,
应使用
Player.getCurrentTracks
。其次,确定了要选择的曲目后
您可以使用 TrackSelectionOverride
在 TrackSelectionParameters
上设置它们。
例如,如需从特定 audioTrackGroup
中选择第一首曲目,请使用以下代码:
player.trackSelectionParameters =
player.trackSelectionParameters
.buildUpon()
.setOverrideForType(
TrackSelectionOverride(audioTrackGroup.mediaTrackGroup, /* trackIndex= */ 0)
)
.build()
player.setTrackSelectionParameters(
player
.getTrackSelectionParameters()
.buildUpon()
.setOverrideForType(
new TrackSelectionOverride(
audioTrackGroup.getMediaTrackGroup(), /* trackIndex= */ 0))
.build());
TrackSelectionOverride
只会应用于包含
TrackGroup
与替换中指定的值完全匹配。因此,
如果后续媒体内容包含
不同曲目
停用轨道类型或轨道组
您可以使用视频、音频或文字等音轨类型
TrackSelectionParameters.Builder.setTrackTypeDisabled
。已停用的轨道类型
将对所有媒体项停用:
player.trackSelectionParameters =
player.trackSelectionParameters
.buildUpon()
.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
.build()
player.setTrackSelectionParameters(
player
.getTrackSelectionParameters()
.buildUpon()
.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ true)
.build());
或者,也可以阻止
TrackGroup
,方法是为该组指定空替换项:
player.trackSelectionParameters =
player.trackSelectionParameters
.buildUpon()
.addOverride(
TrackSelectionOverride(disabledTrackGroup.mediaTrackGroup, /* trackIndices= */ listOf())
)
.build()
player.setTrackSelectionParameters(
player
.getTrackSelectionParameters()
.buildUpon()
.addOverride(
new TrackSelectionOverride(
disabledTrackGroup.getMediaTrackGroup(),
/* trackIndices= */ ImmutableList.of()))
.build());
自定义轨道选择器
轨道的选择由 TrackSelector
(一个实例)负责
每当构建 ExoPlayer
并在稍后获得
与ExoPlayer.getTrackSelector()
共享。
val trackSelector = DefaultTrackSelector(context)
val player = ExoPlayer.Builder(context).setTrackSelector(trackSelector).build()
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
ExoPlayer player = new ExoPlayer.Builder(context).setTrackSelector(trackSelector).build();
DefaultTrackSelector
是一个适合大多数用途的灵活 TrackSelector
案例它使用 Player
中设置的 TrackSelectionParameters
,还使用
提供了一些高级自定义选项,
DefaultTrackSelector.ParametersBuilder
:
trackSelector.setParameters(
trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true))
)
trackSelector.setParameters(
trackSelector.buildUponParameters().setAllowVideoMixedMimeTypeAdaptiveness(true));
隧道
如果渲染程序和
所选曲目支持该功能。为此,请使用
DefaultTrackSelector.ParametersBuilder.setTunnelingEnabled(true)
。
音频分流 (offload)
在以下情况下,您可以启用分流音频播放:
渲染程序和所选轨道支持它为此,请指定
您的TrackSelectionParameters
中的AudioOffloadModePreferences
。
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()
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());
);