Saturday, 26 February 2022

ExoPlayer+CastPlayer add subtitles (closed captions) using MediaItem

I am trying to configure both SimpleExoPlayer and CastPlayer to display subtitles on device/TV. I create MediaItem as follows:

private fun createMediaItem(url: String, type: PlayerViewSourceType): MediaItem {
        val uri = Uri.parse(url)
        val mediaItemBuilder = MediaItem.Builder()
            .setUri(uri)
        if (type == PlayerViewSourceType.HLS) {
            val subtitle = MediaItem.Subtitle(uri, MimeTypes.TEXT_VTT, "en", C.SELECTION_FLAG_AUTOSELECT)
            mediaItemBuilder.apply {
                setMimeType(MimeTypes.APPLICATION_M3U8)
                setSubtitles(listOf(subtitle))
            }
        } else {
            val subtitle = MediaItem.Subtitle(uri, MimeTypes.TEXT_VTT, "en", C.SELECTION_FLAG_AUTOSELECT)
            mediaItemBuilder.apply {
                setMimeType(MimeTypes.APPLICATION_MP4)
                setSubtitles(listOf(subtitle))
            }
        }

        return mediaItemBuilder.build()
    }

I use same url, because subtitles are coming with video and it works this way on iOS side. Also Subtitles object is the same for both cases so could be created before if-else but I tried different sets of parameters so I left it as it is. It didn't work this way. Unfortunatelly addTextOutput {} is deprecated so I've been searching further and I found out that I can add it as Player.Listener implementation, so I created a class:

private inner class SubtitlesListener() : Player.Listener, TextOutput {
        override fun onCues(cues: MutableList<Cue>) {
            subtitleView.onCues(cues)
        }
    }

And with this class I added another listeners for my players:

playerStorage.simpleExoPlayer.addListener(SubtitlesListener())
playerStorage.castPlayer.addListener(SubtitlesListener())

And to zip it all together I added click listener for CC button:

private fun setupSubtitlesClickListener() {
        ccButton.setOnClickListener {
            when (playerStorage.isDisplayingSubtitles) {
                true -> {
                    playerStorage.showSubtitles(false)
                    ccButton.setImageResource(R.drawable.ic_closed_caption_inactive_24_px)
                    subtitleView.gone()
                }
                else -> {
                    playerStorage.showSubtitles(true)
                    ccButton.setImageResource(R.drawable.ic_closed_caption_white_16_px)
                    subtitleView.visible()
                }
            }
        }
    }

For now only one video in app has subtitles for testing purposes and it is .mp4 video file. Unfortunately this solution doesn't work.
I have found plenty implementations for subtitles, but the latest is from 2020 and it is not applicable here. Also I can't use MergingMediaSource because CastPlayer accepts only MediaItem. SimpleExoPlayer can use it too, so I can create one type of object for both players. Even if I would use MediaSource just for SimpleExoPlayer I still couldn't add subtitles for `CastPlayer.

I can use m3u8 for all cases, so I don't need to read files from separate file.



from ExoPlayer+CastPlayer add subtitles (closed captions) using MediaItem

No comments:

Post a Comment