【问题标题】:How to turn On/OFF closed captions in HLS Streaming URL in Exoplayer?如何在 Exoplayer 的 HLS 流 URL 中打开/关闭隐藏式字幕?
【发布时间】:2017-07-14 21:58:20
【问题描述】:

我正在使用 Exoplayer 版本 2.0.4 播放 HLS Streams(.m3u8)。我的 HLS 流包含带有它的隐藏式字幕。如何使用 exoplayer 控制隐藏式字幕?是否可以在需要时隐藏/显示字幕并在需要时更改字幕布局的位置?

【问题讨论】:

  • 嗨拉姆,你能成功显示字幕吗?如果是这样,您可以分享您的代码以使用 Exoplayer 版本 2 添加字幕吗?谢谢
  • 在 Exoplayer 中,我可以通过在 github 项目中使用 SimpleExoplayer View 类来自定义隐藏式字幕。您可以隐藏/显示、更改标题文本字体、颜色、位置...
  • @RamJay 你能显示/隐藏字幕吗?我还设法在 Exoplayer 中显示字幕,但现在想打开/关闭它们。你是怎么做到的?

标签: android exoplayer


【解决方案1】:

我能够使用DefaultTrackSelector 在 ExoPlayer 2 中控制字幕选择。下面的代码是根据ExoPlayer 2 Demo的TrackSelectionHelper类修改的,更多实现细节请参考。

要关闭字幕,您需要禁用文本轨道的渲染器并清除选择覆盖。

trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();

TRACK_TEXT 是我创建的一个局部静态变量,表示与视频/音频轨道相关的文本轨道 (2) 的索引。我相信 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 在布局中定位标题。您的类需要实现 TextRenderer.Output 并覆盖 onCues() 方法。

@Override
public void onCues(List<Cue> cues) {
    if (subtitleView != null) {
        subtitleView.onCues(cues);
    }
}

【讨论】:

  • 在哪里以及如何将字幕 Uri/link 传递给这段代码?
  • @SamRamezanli 请参阅此处了解如何创建媒体源和准备播放器:google.github.io/ExoPlayer/guide.html#preparing-the-player 我们使用 HLS,因此文本和视频轨道都包含在一个清单/url 中。进一步的实现细节基于demo
  • 感谢@Taylor,但我使用的是 DASH,我需要将字幕链接到视频。我目前在您共享的链接中使用相同的解决方案,但是,除非我们释放并重新启动播放器,否则此方法不允许我们启用和禁用字幕。
  • 我遇到了@Sam Ramezanli 提到的同样的问题,我有一个场景,比如切换到下一个剪辑时,上一个视频的关闭字幕将显示在当前剪辑中。我可以知道如何控制这种问题。
  • 对我来说这个答案不起作用..我使用的是 exoplayer 2.7.1 版
【解决方案2】:

在我的应用程序中,我按如下方式初始化 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()
    );

【讨论】:

  • 像魅力一样工作
  • 您可能需要设置首选语言。
【解决方案3】:

将 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);

【讨论】:

  • 你从哪里得到newSubtitle
  • 您的回答非常好,但 newSubtitle 具有误导性。虽然没有投反对票..
【解决方案4】:

要禁用轨道,比如字幕(文本)轨道,您需要使用您之前传递给 ExoPlayerFactory.newSimpleInstanceDefaultTrackSelector,来禁用您需要它的轨道渲染器索引。在ExoPlayer中选择曲目实际上有两个令人困惑的(至少对我而言!)术语,一个是TrackType,另一个是RendererIndex .基本上有一些 TrackTypes 可以在 com.google.android.exoplayer2.C 类中访问,主要有 TRACK_TYPE_AUDIOTRACK_TYPE_VIDEOTRACK_TYPE_TEXT。但另一方面 rendererIndex 可以是从 0 开始的任何数字(我猜)。因此,要禁用轨道,您需要先找到它的 rendererIndex。然后使用下面的代码禁用轨道:

trackSelector
            ?.buildUponParameters()
            ?.setRendererDisabled(rendererIndex, true)
            ?.let {
                trackSelector?.setParameters(it)
            }

【讨论】:

    【解决方案5】:

    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;
    }
    

    【讨论】:

      【解决方案6】:

      我强烈建议不要像这样使用常量 TRACK_TEXTC.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()
          }
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-20
        • 2018-04-15
        • 1970-01-01
        • 2014-06-23
        • 1970-01-01
        • 2015-08-31
        • 2015-10-09
        • 2017-07-02
        相关资源
        最近更新 更多