How to turn On/OFF closed captions in HLS Streaming URL in Exoplayer?
I was able to control caption selection in ExoPlayer 2 using a DefaultTrackSelector
. The code below was modified based on the ExoPlayer 2 Demo's TrackSelectionHelper
class, which should be referenced for more implementation details.
To turn captions off, you need to disable the renderer for the text tracks and clear the selection overrides.
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
TRACK_TEXT
is a local static variable I created representing the index of the text tracks (2), in relation to video/audio tracks. I believe that SelectionOverrides are just programmatically specified track selections.
To enable the tracks again, you need to enable the renderer for text tracks, and then set up a new SelectionOverride
for your desired text track. Before you can do this, you need to get the TrackGroupArray
of the currently mapped text tracks from your DefaultTrackSelector
.
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);
For more implementation details (e.g., initializing the trackSelector and fixedFactory), check out the ExoPlayer 2 Demo.
You can use a SubtitleView
to position the captions within your layout. Your class will need to implement TextRenderer.Output
and override the onCues()
method.
@Override
public void onCues(List<Cue> cues) {
if (subtitleView != null) {
subtitleView.onCues(cues);
}
}
After updating the ExoPlayer library to
implementation 'com.google.android.exoplayer:exoplayer:2.9.5'
I found that the MappingTrackSelector.SelectionOverride
method does not exist anymore.
I was unable to find a working alternative, as just replacing with DefaultTrackSelector.SelectionOverride
didn't work for me, and subtitles were not playing in my case for video.
MediaSource mediaSource = new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
Final set of lines which worked for me:
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);
Old code was:
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);
To close subtitles:
DefaultTrackSelector.ParametersBuilder paramsBuilder = trackSelector.buildUponParameters();
paramsBuilder.setRendererDisabled(playingSubtitle.renderIndex, true);
trackSelector.setParameters(paramsBuilder);
In my application I initialize the trackselecktor
as follow
To turn off close captions from video track
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, true)
.build()
);
To turn on close captions from video track
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelector.setParameters(new DefaultTrackSelector.ParametersBuilder()
.setRendererDisabled(C.TRACK_TYPE_VIDEO, false)
.build()
);
I highly recommend don't use the constant TRACK_TEXT
or C.TRACK_TYPE_TEXT
as this:
trackSelector.setRendererDisabled(TRACK_TEXT, true);
trackSelector.clearSelectionOverrides();
because it could vary depends on the asset which you are using, you can ensure that you are disabling the correct renderer with the following code (Kotlin version):
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()
}
}