mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-16 02:44:51 +00:00
fix(subtitles): fix external subtitles
This commit is contained in:
@@ -13,6 +13,7 @@ import androidx.media3.common.AudioAttributes
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.DefaultHttpDataSource
|
||||
@@ -187,6 +188,19 @@ class OmniPlayer(
|
||||
super.dispose()
|
||||
}
|
||||
|
||||
private fun inferSubtitleMimeType(link: String): String? {
|
||||
val ext = link.toUri().lastPathSegment?.substringAfterLast('.', "")?.lowercase()
|
||||
return when (ext) {
|
||||
"vtt", "webvtt" -> MimeTypes.TEXT_VTT
|
||||
"srt" -> MimeTypes.APPLICATION_SUBRIP
|
||||
"ass", "ssa" -> MimeTypes.TEXT_SSA
|
||||
"ttml", "dfxp", "xml" -> MimeTypes.APPLICATION_TTML
|
||||
"sup" -> MimeTypes.APPLICATION_PGS
|
||||
"sub" -> MimeTypes.APPLICATION_VOBSUB
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildMediaItem(
|
||||
src: com.margelo.nitro.omni.VideoSrc,
|
||||
metadata: com.margelo.nitro.omni.Metadata?,
|
||||
@@ -212,7 +226,10 @@ class OmniPlayer(
|
||||
.setId(subtitle.id)
|
||||
.setLanguage(subtitle.language)
|
||||
.setLabel(subtitle.label)
|
||||
.setMimeType(subtitle.mimeType)
|
||||
// exoplayer requires a mime type to pick a subtitle parser.
|
||||
// fall back to inferring it from the link's extension so
|
||||
// consumers don't have to provide one.
|
||||
.setMimeType(subtitle.mimeType ?: inferSubtitleMimeType(subtitle.link))
|
||||
.build()
|
||||
})
|
||||
.setRequestMetadata(
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.videolan.libvlc.MediaPlayer
|
||||
import org.videolan.libvlc.interfaces.IMedia
|
||||
import org.videolan.libvlc.interfaces.IMedia.VideoTrack
|
||||
import org.videolan.libvlc.interfaces.IVLCVout
|
||||
import java.security.MessageDigest
|
||||
|
||||
@SuppressLint("UnsafeOptInUsageError")
|
||||
class VlcPlayer(ctx: Context) :
|
||||
@@ -387,6 +388,20 @@ class VlcPlayer(ctx: Context) :
|
||||
}
|
||||
}
|
||||
|
||||
// vlc keys each slave's tracks by the md5 of its uri ("<md5(uri)>/spu/<n>")
|
||||
private fun subtitleSlaveForTrackId(trackId: String): MediaItem.SubtitleConfiguration? {
|
||||
val hash = trackId.substringBefore("/spu/", "")
|
||||
if (hash.isEmpty()) return null
|
||||
return mediaItems.getOrNull(currentMediaItemIndex)
|
||||
?.localConfiguration?.subtitleConfigurations
|
||||
?.firstOrNull { md5(it.uri.toString()) == hash }
|
||||
}
|
||||
|
||||
private fun md5(value: String): String =
|
||||
MessageDigest.getInstance("MD5")
|
||||
.digest(value.toByteArray())
|
||||
.joinToString("") { "%02x".format(it.toInt() and 0xFF) }
|
||||
|
||||
// vlc doesn't allow arbitrary headers :c
|
||||
private fun applyRequestHeaders(media: Media, extras: Bundle?) {
|
||||
if (extras == null) return
|
||||
@@ -599,10 +614,12 @@ class VlcPlayer(ctx: Context) :
|
||||
}
|
||||
|
||||
player.getTracks(IMedia.Track.Type.Text)?.forEach { track ->
|
||||
// external subs don't have label/language, match them back to surface them
|
||||
val slave = subtitleSlaveForTrackId(track.id)
|
||||
val format = Format.Builder()
|
||||
.setId(track.id)
|
||||
.setLabel(track.name)
|
||||
.setLanguage(track.language)
|
||||
.setLabel(slave?.label ?: track.name)
|
||||
.setLanguage(slave?.language ?: track.language)
|
||||
.setSampleMimeType("text/x-unknown")
|
||||
.build()
|
||||
val group = TrackGroup("vlc-sub-${track.id}", format)
|
||||
|
||||
Reference in New Issue
Block a user