Search code examples
androidexoplayerexoplayer2.x

ExoPlayer HLS Text Track Missing


With ExoPlayer 2.18.2 I'm initializing a DefaultTrackSelector

trackSelector = DefaultTrackSelector(requireContext())

And attaching it to a player

private fun createContentPlayer() {
    val renderersFactory = DefaultRenderersFactory(requireContext())
    this.trackSelector = DefaultTrackSelector(requireContext())

    val player = ExoPlayer.Builder(requireContext())
        .setRenderersFactory(renderersFactory)
        .setTrackSelector(this.trackSelector!!)
        .build()

    this.contentPlayer = player
}

So I have this method where I'm retrieving the text renderer index

private fun getTextRenderIndex(): Int {
    val count = contentPlayer?.rendererCount ?: 0
    for (i: Int in 0..count) {
        if (contentPlayer?.getRendererType(i) == C.TRACK_TYPE_TEXT) {
            return i
        }
    }

    return -1
}

The text renderer index is always 2 (see index in the screenshot below)

Here's how the media source is prepared

val uri = Uri.parse("video.m3u8")

val dataSourceFactory = DefaultDataSource.Factory(requireContext())

val mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(uri))

contentPlayer?.setMediaSource(mediaSource)
contentPlayer?.prepare()

Ok no problem so far but then if I call

val mappedTrackInfo = trackSelector?.currentMappedTrackInfo

And then look at then MappedTrackInfo object in the debugger, renderer names are

["MediaCodecVideo...", "MediaCodecAudio...", "TextRenderer", "MetadataRendere...", "CameraMotionRen..."]

But rendererTrackGroups in this same object shows no text tracks

enter image description here

Why is the text renderer missing?

Videos the app is playing are .m3u8 and often times have closed captions embedded. Yet I've not up to this point seen any closed captions render. So I'm guessing the reason is the text renderer track is not present.

My goal is to be able to turn on / off closed captioning for videos with the following code

val length = trackGroupArray?.length ?: 0
if (length > 0) {
    val trackGroup = trackGroupArray!![0]

    val currentParamsBuilder = trackSelector?.buildUponParameters()
            ?: DefaultTrackSelector.Parameters.Builder(requireContext())

    val disabled = !enabled

    if (trackGroup.length > 0) {
        val selectionOverride = TrackSelectionOverride(trackGroup, 0)
        val newParameters = currentParamsBuilder
            .setRendererDisabled(textRenderIndex, disabled)
            .clearOverridesOfType(TRACK_TYPE_TEXT)
            .addOverride(selectionOverride)
            .build()

        trackSelector?.parameters = newParameters
    }
}

Solution

  • Starting in 2.17.0 HlsMediaSource uses chunkless preparation by default. If HLS streams do not declare closed captions in the master playlist then they won't be available during playback and the text track wont be there.

    Either add them to the master playlist or turn off chunkless preparation.

    HlsMediaSource.Factory.setAllowChunklessPreparation(false)
    

    Source https://github.com/google/ExoPlayer/blob/release-v2/RELEASENOTES.md