Enable support for WebVTT and TTML subtitles for the player (#4377)
All subtitle formats used to be enabled by default in older versions of media3. After the media3 library was upgraded to 1.3.0, Extractors should specify a `SubtitleParser.Factory` explicitly. By default, no subtitle formats are supported when using the now deprecated empty constructor of Extractors. Limit support to **WebVTT** and **TTML** which are the only true web standards amongst all the subtitle formats supported by ExoPlayer. Note that only subtitles embedded in MP4 and WebM files are supported until Mastodon provides a way to upload subtitles separately.
This commit is contained in:
parent
4e822c9a0a
commit
72ee0b4292
|
@ -21,6 +21,8 @@ import android.content.Context
|
|||
import android.os.Looper
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.Format
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.datasource.DataSource
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
|
@ -44,6 +46,10 @@ import androidx.media3.extractor.mp3.Mp3Extractor
|
|||
import androidx.media3.extractor.mp4.FragmentedMp4Extractor
|
||||
import androidx.media3.extractor.mp4.Mp4Extractor
|
||||
import androidx.media3.extractor.ogg.OggExtractor
|
||||
import androidx.media3.extractor.text.SubtitleParser
|
||||
import androidx.media3.extractor.text.ttml.TtmlParser
|
||||
import androidx.media3.extractor.text.webvtt.Mp4WebvttParser
|
||||
import androidx.media3.extractor.text.webvtt.WebvttParser
|
||||
import androidx.media3.extractor.wav.WavExtractor
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
@ -98,17 +104,50 @@ object PlayerModule {
|
|||
}
|
||||
|
||||
@Provides
|
||||
fun provideExtractorsFactory(): ExtractorsFactory {
|
||||
fun providesSubtitleParserFactory(): SubtitleParser.Factory {
|
||||
return object : SubtitleParser.Factory {
|
||||
override fun supportsFormat(format: Format): Boolean {
|
||||
return when (format.sampleMimeType) {
|
||||
MimeTypes.TEXT_VTT,
|
||||
MimeTypes.APPLICATION_MP4VTT,
|
||||
MimeTypes.APPLICATION_TTML -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCueReplacementBehavior(format: Format): Int {
|
||||
return when (val mimeType = format.sampleMimeType) {
|
||||
MimeTypes.TEXT_VTT -> WebvttParser.CUE_REPLACEMENT_BEHAVIOR
|
||||
MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttParser.CUE_REPLACEMENT_BEHAVIOR
|
||||
MimeTypes.APPLICATION_TTML -> TtmlParser.CUE_REPLACEMENT_BEHAVIOR
|
||||
else -> throw IllegalArgumentException("Unsupported MIME type: $mimeType")
|
||||
}
|
||||
}
|
||||
|
||||
override fun create(format: Format): SubtitleParser {
|
||||
return when (val mimeType = format.sampleMimeType) {
|
||||
MimeTypes.TEXT_VTT -> WebvttParser()
|
||||
MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttParser()
|
||||
MimeTypes.APPLICATION_TTML -> TtmlParser()
|
||||
else -> throw IllegalArgumentException("Unsupported MIME type: $mimeType")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideExtractorsFactory(subtitleParserFactory: SubtitleParser.Factory): ExtractorsFactory {
|
||||
// Extractors order is optimized according to
|
||||
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ
|
||||
return ExtractorsFactory {
|
||||
arrayOf(
|
||||
FlacExtractor(),
|
||||
WavExtractor(),
|
||||
Mp4Extractor(),
|
||||
FragmentedMp4Extractor(),
|
||||
Mp4Extractor(subtitleParserFactory),
|
||||
FragmentedMp4Extractor(subtitleParserFactory),
|
||||
OggExtractor(),
|
||||
MatroskaExtractor(),
|
||||
MatroskaExtractor(subtitleParserFactory),
|
||||
Mp3Extractor()
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue