Dapatkan dan alihkan subtitle WebVTT di ExoPlayer

Halo semuanya.

Beberapa hari yang lalu ada tugas untuk mengganti subtitle WebVTT dalam aliran HLS.
Kami memutar video menggunakan ExoPlayer, dan pada awalnya sepertinya Google dan Co. seharusnya memberikan solusi dari kotak "take and done". Namun kenyataannya tidak sesuai dengan harapan :)

Googling dan Habring tidak membuahkan hasil dan semuanya muncul untuk memilih aplikasi demo resmi ExoPlayer.

Karena Karena artikel mengasumsikan keakraban dengan struktur HLS dan keberadaan beberapa pengalaman dalam ExoPlayer, kami langsung ke pokok permasalahan.

Inilah yang dikatakan dokumentasi tentang perpindahan aliran (video, audio, subtitle). Dan dia hampir tidak memberi tahu kita apa pun - menginisialisasi pemain menggunakan DefaultTrackSelector dan menggunakannya. Itu saja, ok :)

Semua subtitle dalam bentuk apa pun (CEA-608, WebVtt) seperti trek lain disimpan di dalam DefaultTrackSelector dan Anda harus bisa mendapatkannya. Semuanya dibagi menjadi beberapa kelompok dan subkelompok, dan singkatnya, struktur internal terlihat seperti ini:


Sekarang mari kita coba untuk mendapatkan subtitle dari tipe WebVTT, mereka harus disimpan di dalam Renderer dengan tipe "3" (C.TRACK_TYPE_TEXT - konstanta dalam Exo):

fun getVttSubtitles(): List<String> {
        val tracks = mutableListOf<String>()
        //  MappedTrackInfo
        defaultTrackSelector.currentMappedTrackInfo?.let { mappedTrackInfo ->
            val renderCount = mappedTrackInfo.rendererCount
            for (renderIndex in 0 until renderCount) {
                //    renderer'    TEXT
                val renderType = mappedTrackInfo.getRendererType(renderIndex)
                if (renderType == C.TRACK_TYPE_TEXT) {
                    val trackGroupArray = mappedTrackInfo.getTrackGroups(renderIndex)
                    //    
                    for (trackGroupArrayIndex in 0 until trackGroupArray.length) {
                        val trackGroup = trackGroupArray[trackGroupArrayIndex]
                        for (trackGroupIndex in 0 until trackGroup.length) {
                            //       TEXT_VTT
                            val format = trackGroup.getFormat(trackGroupIndex)
                            if (format.sampleMimeType == MimeTypes.TEXT_VTT) {
                                tracks += format.language.orEmpty()
                            }
                        }
                    }
                }
            }
        }

        return tracks
    }

Seperti yang Anda lihat, beberapa cara mudah untuk beralih dan pencarian tidak disediakan dan Anda harus melakukan semua loop dengan pena.

Tetapi kita perlu tahu tidak hanya tentang daftar itu sendiri, tetapi juga tentang opsi yang dipilih (yang akan kita pilih di masa depan). Karena suatu alasan, Anda tidak bisa mendapatkan trek yang dipilih dari DefaultTrackSelector, tetapi Anda bisa menggunakan ExoPlayer itu sendiri. Skema untuk mendapatkan kira-kira sama, kita melangkah lebih dalam, tetapi di sini kita melewatkan bagian melalui renderers:

fun getSelectedVttSubtitles(): List<String> {
        val selectedLangs = mutableListOf<String>()
        val currentTrackSelections = exoPlayer.currentTrackSelections
        for (selectionIndex in 0 until currentTrackSelections.length) {
            val trackSelection = currentTrackSelections[selectionIndex]
            if (trackSelection != null) {
                //     
                val length = trackSelection.length()
                for (trackIndex in 0 until length) {
                    //      
                    val format = trackSelection.getFormat(trackIndex)
                    if (format.sampleMimeType == MimeTypes.TEXT_VTT) {
                        selectedLangs += format.language.orEmpty()
                    }
                }
            }
        }

        return selectedLangs
    }

Kami memiliki daftar umum dan daftar yang dipilih. Cara menggabungkan dan menampilkan pada UI bukan tujuan dari artikel ini. Ada banyak cara. Kami hanya harus belajar cara mengatur trek.

Untuk kejelasan, kami akan melakukan ini dengan cara dahi, sehingga semua siklus dan indeks jelas.

Pemasangan trek dengan kode bahasanya ("ru", "en", ...):

fun selectTrackByIsoCodeAndType(langCode: String) {
        defaultTrackSelector.currentMappedTrackInfo?.let { mappedTrackInfo ->
            //         
            val renderCount = mappedTrackInfo.rendererCount
            for (renderIndex in 0 until renderCount) {
                //    renderer'    TEXT
                val renderType = mappedTrackInfo.getRendererType(renderIndex)
                if (renderType == C.TRACK_TYPE_TEXT) {
                    val trackGroupArray = mappedTrackInfo.getTrackGroups(renderIndex)
                    //    
                    for (trackGroupArrayIndex in 0 until trackGroupArray.length) {
                        val trackGroup = trackGroupArray[trackGroupArrayIndex]
                        for (trackGroupIndex in 0 until trackGroup.length) {
                            val format = trackGroup.getFormat(trackGroupIndex)
                            //       
                            if (format.sampleMimeType == MimeTypes.TEXT_VTT
                                && format.language == langCode
                            ) {
                                //    
                                val currentParams = defaultTrackSelector.buildUponParameters()
                                //   ( )
                                //  
                                currentParams.clearSelectionOverride(
                                    renderIndex, trackGroupArray
                                )

                                // ,    
                                //       

                                //       
                                val override = DefaultTrackSelector.SelectionOverride(
                                    trackGroupArrayIndex, trackGroupIndex
                                )

                                //     
                                currentParams.setSelectionOverride(
                                    renderIndex,
                                    trackGroupArray,
                                    override
                                )

                                //     
                                defaultTrackSelector.setParameters(currentParams)

                                return
                            }
                        }
                    }
                }
            }
        }
    }

Kesimpulan


Kami telah membahas dasar-dasar cara mendapatkan dan mengganti subtitle WebVTT di ExoPlayer.
Pada kenyataannya, metode yang sama dapat dengan mudah bekerja dengan subtitle jenis lain - itu cukup untuk parameterisasi metode dengan jenis subtitle. Dengan cara yang sama, tidak akan sulit untuk bekerja dengan trek audio. Tentu saja, cukup sulit untuk menggunakan solusi dalam formulir ini dan diharuskan untuk membawanya ke bentuk yang lebih nyaman.

Terimakasih atas perhatiannya.

All Articles