使用AndroidX Media3 ExoPlayer与
useController=false
和自定义Jetpack Compose控件,如何使HLS嵌入视频字幕自动显示并提供一个按钮来选择/禁用它们?
注意:这与如何使用 ExoPlayer 3 和 Compose 显示 HLS 字幕?不是同一个问题。感谢您的帮助!
@Composable
fun MyPlayer() {
val hlsUri = Uri.parse("https://some.website/video.m3u8")
val context = LocalContext.current
val player: ExoPlayer = remember {
ExoPlayer.Builder(context)
.build()
.apply {
setMediaItem(MediaItem.fromUri(hlsUri))
prepare()
}
}
AndroidView(
factory = {
PlayerView(context).apply {
this.player = player
useController = false // <- because of this, setShowSubtitleButton(true) is not a solution
layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
}
}
)
// Custom Jetpack Compose controls (play, pause, show/hide subtitles, etc) are added below
// ...
}
依赖关系:
# gradle/libs.versions.toml
androidXMedia = "1.1.0"
androidx-media-player = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "androidXMedia" }
androidx-media-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "androidXMedia" }
androidx-media-hls = { group = "androidx.media3", name = "media3-exoplayer-hls", version.ref = "androidXMedia" }
// app/build.gradle.kts
dependencies {
// ...
implementation(libs.androidx.media.player)
implementation(libs.androidx.media.ui)
implementation(libs.androidx.media.hls)
}
HLS 文件如下所示:
#EXTM3U
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",LANGUAGE="en",URI="https://.../playlist.m3u8",AUTOSELECT=YES,DEFAULT=NO
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Français",LANGUAGE="fr",URI="https://.../playlist.m3u8",AUTOSELECT=YES,DEFAULT=NO
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-medium",NAME="audio",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="https://.../playlist.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-high",NAME="audio",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="https://.../playlist.m3u8"
#EXT-X-STREAM-INF:SUBTITLES="subs",BANDWIDTH=2255226,AVERAGE-BANDWIDTH=1578000,RESOLUTION=1280x720,FRAME-RATE=24.000,CODECS="avc1.640020,mp4a.40.2",AUDIO="audio-high"
https://.../playlist.m3u8
#EXT-X-STREAM-INF:SUBTITLES="subs",BANDWIDTH=698963,AVERAGE-BANDWIDTH=537000,RESOLUTION=640x360,FRAME-RATE=24.000,CODECS="avc1.64001E,mp4a.40.2",AUDIO="audio-medium"
https://.../playlist.m3u8
#EXT-X-STREAM-INF:SUBTITLES="subs",BANDWIDTH=463242,AVERAGE-BANDWIDTH=332000,RESOLUTION=426x240,FRAME-RATE=24.000,CODECS="avc1.640015,mp4a.40.2",AUDIO="audio-medium"
https://.../playlist.m3u8
#EXT-X-STREAM-INF:SUBTITLES="subs",BANDWIDTH=5496152,AVERAGE-BANDWIDTH=4096000,RESOLUTION=1920x1080,FRAME-RATE=24.000,CODECS="avc1.640028,mp4a.40.2",AUDIO="audio-high"
https://.../playlist.m3u8
#EXT-X-STREAM-INF:SUBTITLES="subs",BANDWIDTH=1440054,AVERAGE-BANDWIDTH=965000,RESOLUTION=960x540,FRAME-RATE=24.000,CODECS="avc1.64001F,mp4a.40.2",AUDIO="audio-medium"
https://.../playlist.m3u8
我查看了PlayerControllerView中的代码并稍微修改了一下。我的情况很简单,只有一个字幕轨道,所以你的情况可能会有所不同。 我将它作为 exoplayer 的扩展功能,我切换 showSubtitles 可变状态,并在 LaunchedEffect 块中切换状态更改时的字幕。
if (!showSubtitles) {
val trackSelectionParameters: TrackSelectionParameters = this.trackSelectionParameters
this.trackSelectionParameters = trackSelectionParameters
.buildUpon()
.clearOverridesOfType(C.TRACK_TYPE_TEXT)
.setIgnoredTextSelectionFlags(C.SELECTION_FLAG_FORCED.inv())
.build()
} else {
val trackSelectionParameters: TrackSelectionParameters = this.trackSelectionParameters
val group = this.currentTracks.groups.firstOrNull {
it.type == C.TRACK_TYPE_TEXT
}?.mediaTrackGroup
if (group != null) {
this.trackSelectionParameters = trackSelectionParameters
.buildUpon()
.setOverrideForType(
TrackSelectionOverride(
group, ImmutableList.of(0)
)
)
.setTrackTypeDisabled(group.type, false)
.build()
}
}