如何在 Exoplayer 的 HLS Streaming URL 中打开 On/OFF 隐藏式字幕?
How to turn On/OFF closed captions in HLS Streaming URL in Exoplayer?
我正在使用 Exoplayer 版本 2.0.4 播放 HLS 流(.m3u8)。我的 HLS 流包含隐藏式字幕。我如何使用 exoplayer 控制隐藏式字幕?可不可以hide/show需要时加字幕,需要时改变字幕布局的位置?
我能够使用 DefaultTrackSelector
在 ExoPlayer 2 中控制字幕选择。下面的代码是根据ExoPlayer 2 Demo的TrackSelectionHelper
class修改的,更多实现细节可以参考
要关闭字幕,您需要禁用文本轨道的渲染器并清除选择覆盖。
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
TRACK_TEXT
是我创建的局部静态变量,代表文本轨道 (2) 的索引,与 video/audio 轨道相关。我相信 SelectionOverrides 只是以编程方式指定的轨道选择。
要再次启用轨道,您需要为文本轨道启用渲染器,然后为您想要的文本轨道设置一个新的 SelectionOverride
。在执行此操作之前,您需要从 DefaultTrackSelector
.
中获取当前映射的文本轨道的 TrackGroupArray
MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
TrackGroupArray textGroups = mappedTrackInfo.getTrackGroups(TRACK_TEXT); // list of captions
int groupIndex = 1; // index of desired caption track within the textGroups array
trackSelector.setRendererDisabled(TRACK_TEXT, false);
MappingTrackSelector.SelectionOverride override =
new MappingTrackSelector.SelectionOverride(fixedFactory, groupIndex, 0);
trackSelector.setSelectionOverride(TRACK_TEXT, textGroups, override);
有关更多实现细节(例如,初始化 trackSelector 和 fixedFactory),请查看 ExoPlayer 2 Demo。
您可以使用 SubtitleView
在布局中定位字幕。您的 class 将需要实施 TextRenderer.Output
并覆盖 onCues()
方法。
@Override
public void onCues(List<Cue> cues) {
if (subtitleView != null) {
subtitleView.onCues(cues);
}
}
在我的应用程序中,我将 trackselecktor
初始化如下
关闭视频轨道的隐藏式字幕
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, true)
.build()
);
打开视频轨道的隐藏式字幕
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, false)
.build()
);
更新ExoPlayer库后
implementation 'com.google.android.exoplayer:exoplayer:2.9.5'
我发现 MappingTrackSelector.SelectionOverride
方法已经不存在了。
我无法找到可行的替代方案,因为仅替换为 DefaultTrackSelector.SelectionOverride
对我不起作用,而且我的视频没有播放字幕。
MediaSource mediaSource = new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
最后一组对我有用的行:
TrackGroupArray trackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(newSubtitle.renderIndex);
DefaultTrackSelector.ParametersBuilder paramsBuilder = trackSelector.buildUponParameters();
DefaultTrackSelector.SelectionOverride sOverride = new DefaultTrackSelector.SelectionOverride(newSubtitle.groupIndex, newSubtitle.indexWithinGroup);
boolean isDisabled = trackSelector.getParameters().getRendererDisabled(newSubtitle.renderIndex);
paramsBuilder.setRendererDisabled(newSubtitle.renderIndex, isDisabled);
if (sOverride != null) {
paramsBuilder.setSelectionOverride(newSubtitle.renderIndex, trackGroups, sOverride);
} else {
paramsBuilder.clearSelectionOverrides(newSubtitle.renderIndex);
}
trackSelector.setParameters(paramsBuilder);
旧代码是:
TrackGroupArray trackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(newSubtitle.renderIndex);
MappingTrackSelector.SelectionOverride sOverride = new MappingTrackSelector.SelectionOverride(
new FixedTrackSelection.Factory(),
newSubtitle.groupIndex,
newSubtitle.indexWithinGroup
);
trackSelector.setSelectionOverride(newSubtitle.renderIndex, trackGroups, sOverride);
trackSelector.setRendererDisabled(newSubtitle.renderIndex, false);
关闭字幕:
DefaultTrackSelector.ParametersBuilder paramsBuilder = trackSelector.buildUponParameters();
paramsBuilder.setRendererDisabled(playingSubtitle.renderIndex, true);
trackSelector.setParameters(paramsBuilder);
要禁用轨道,比方说字幕(文本)轨道,您需要使用您之前传递给 ExoPlayerFactory.newSimpleInstance
的 DefaultTrackSelector 来禁用track 你需要它的 rendererIndex。在 ExoPlayer 中选择曲目实际上有两个令人困惑的术语(至少对我而言!),一个是 TrackType,另一个是 渲染器索引。基本上有一些TrackTypes可以在com.google.android.exoplayer2.C class中访问,主要的是TRACK_TYPE_AUDIO、TRACK_TYPE_VIDEO 和 TRACK_TYPE_TEXT。但另一方面 rendererIndex 可以是从 0 开始的任何数字(我猜)。因此,要禁用轨道,您需要先找到它的 rendererIndex。然后使用下面的代码禁用轨道:
trackSelector
?.buildUponParameters()
?.setRendererDisabled(rendererIndex, true)
?.let {
trackSelector?.setParameters(it)
}
Xamarin.Android 的解决方案:
[Obsolete]
private DefaultTrackSelector CreateTrackSelector()
{
var bandwidthMeter = new DefaultBandwidthMeter();
var videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
var trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
var trackParameter = new DefaultTrackSelector.ParametersBuilder()
// disables closed caption / subtitle
.SetDisabledTextTrackSelectionFlags(C.TrackTypeText)
.Build();
trackSelector.SetParameters(trackParameter);
return trackSelector;
}
我强烈建议不要像这样使用常量 TRACK_TEXT
或 C.TRACK_TYPE_TEXT
:
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
因为它可能因您使用的资产而异,您可以确保使用以下代码(Kotlin 版本)禁用正确的渲染器:
private fun disableSubtitles(){
(0 until (trackSelector.currentMappedTrackInfo?.rendererCount ?: 0)).filter {position ->
player.getRendererType(position) == C.TRACK_TYPE_TEXT
}.map {position ->
trackSelector.parameters = trackSelector.buildUponParameters()
.setRendererDisabled(position,true)
.clearSelectionOverrides(position)
.build()
}
}
我正在使用 Exoplayer 版本 2.0.4 播放 HLS 流(.m3u8)。我的 HLS 流包含隐藏式字幕。我如何使用 exoplayer 控制隐藏式字幕?可不可以hide/show需要时加字幕,需要时改变字幕布局的位置?
我能够使用 DefaultTrackSelector
在 ExoPlayer 2 中控制字幕选择。下面的代码是根据ExoPlayer 2 Demo的TrackSelectionHelper
class修改的,更多实现细节可以参考
要关闭字幕,您需要禁用文本轨道的渲染器并清除选择覆盖。
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
TRACK_TEXT
是我创建的局部静态变量,代表文本轨道 (2) 的索引,与 video/audio 轨道相关。我相信 SelectionOverrides 只是以编程方式指定的轨道选择。
要再次启用轨道,您需要为文本轨道启用渲染器,然后为您想要的文本轨道设置一个新的 SelectionOverride
。在执行此操作之前,您需要从 DefaultTrackSelector
.
TrackGroupArray
MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
TrackGroupArray textGroups = mappedTrackInfo.getTrackGroups(TRACK_TEXT); // list of captions
int groupIndex = 1; // index of desired caption track within the textGroups array
trackSelector.setRendererDisabled(TRACK_TEXT, false);
MappingTrackSelector.SelectionOverride override =
new MappingTrackSelector.SelectionOverride(fixedFactory, groupIndex, 0);
trackSelector.setSelectionOverride(TRACK_TEXT, textGroups, override);
有关更多实现细节(例如,初始化 trackSelector 和 fixedFactory),请查看 ExoPlayer 2 Demo。
您可以使用 SubtitleView
在布局中定位字幕。您的 class 将需要实施 TextRenderer.Output
并覆盖 onCues()
方法。
@Override
public void onCues(List<Cue> cues) {
if (subtitleView != null) {
subtitleView.onCues(cues);
}
}
在我的应用程序中,我将 trackselecktor
初始化如下
关闭视频轨道的隐藏式字幕
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, true)
.build()
);
打开视频轨道的隐藏式字幕
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, false)
.build()
);
更新ExoPlayer库后
implementation 'com.google.android.exoplayer:exoplayer:2.9.5'
我发现 MappingTrackSelector.SelectionOverride
方法已经不存在了。
我无法找到可行的替代方案,因为仅替换为 DefaultTrackSelector.SelectionOverride
对我不起作用,而且我的视频没有播放字幕。
MediaSource mediaSource = new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
最后一组对我有用的行:
TrackGroupArray trackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(newSubtitle.renderIndex);
DefaultTrackSelector.ParametersBuilder paramsBuilder = trackSelector.buildUponParameters();
DefaultTrackSelector.SelectionOverride sOverride = new DefaultTrackSelector.SelectionOverride(newSubtitle.groupIndex, newSubtitle.indexWithinGroup);
boolean isDisabled = trackSelector.getParameters().getRendererDisabled(newSubtitle.renderIndex);
paramsBuilder.setRendererDisabled(newSubtitle.renderIndex, isDisabled);
if (sOverride != null) {
paramsBuilder.setSelectionOverride(newSubtitle.renderIndex, trackGroups, sOverride);
} else {
paramsBuilder.clearSelectionOverrides(newSubtitle.renderIndex);
}
trackSelector.setParameters(paramsBuilder);
旧代码是:
TrackGroupArray trackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(newSubtitle.renderIndex);
MappingTrackSelector.SelectionOverride sOverride = new MappingTrackSelector.SelectionOverride(
new FixedTrackSelection.Factory(),
newSubtitle.groupIndex,
newSubtitle.indexWithinGroup
);
trackSelector.setSelectionOverride(newSubtitle.renderIndex, trackGroups, sOverride);
trackSelector.setRendererDisabled(newSubtitle.renderIndex, false);
关闭字幕:
DefaultTrackSelector.ParametersBuilder paramsBuilder = trackSelector.buildUponParameters();
paramsBuilder.setRendererDisabled(playingSubtitle.renderIndex, true);
trackSelector.setParameters(paramsBuilder);
要禁用轨道,比方说字幕(文本)轨道,您需要使用您之前传递给 ExoPlayerFactory.newSimpleInstance
的 DefaultTrackSelector 来禁用track 你需要它的 rendererIndex。在 ExoPlayer 中选择曲目实际上有两个令人困惑的术语(至少对我而言!),一个是 TrackType,另一个是 渲染器索引。基本上有一些TrackTypes可以在com.google.android.exoplayer2.C class中访问,主要的是TRACK_TYPE_AUDIO、TRACK_TYPE_VIDEO 和 TRACK_TYPE_TEXT。但另一方面 rendererIndex 可以是从 0 开始的任何数字(我猜)。因此,要禁用轨道,您需要先找到它的 rendererIndex。然后使用下面的代码禁用轨道:
trackSelector
?.buildUponParameters()
?.setRendererDisabled(rendererIndex, true)
?.let {
trackSelector?.setParameters(it)
}
Xamarin.Android 的解决方案:
[Obsolete]
private DefaultTrackSelector CreateTrackSelector()
{
var bandwidthMeter = new DefaultBandwidthMeter();
var videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
var trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
var trackParameter = new DefaultTrackSelector.ParametersBuilder()
// disables closed caption / subtitle
.SetDisabledTextTrackSelectionFlags(C.TrackTypeText)
.Build();
trackSelector.SetParameters(trackParameter);
return trackSelector;
}
我强烈建议不要像这样使用常量 TRACK_TEXT
或 C.TRACK_TYPE_TEXT
:
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
因为它可能因您使用的资产而异,您可以确保使用以下代码(Kotlin 版本)禁用正确的渲染器:
private fun disableSubtitles(){
(0 until (trackSelector.currentMappedTrackInfo?.rendererCount ?: 0)).filter {position ->
player.getRendererType(position) == C.TRACK_TYPE_TEXT
}.map {position ->
trackSelector.parameters = trackSelector.buildUponParameters()
.setRendererDisabled(position,true)
.clearSelectionOverrides(position)
.build()
}
}