ExoPlayer 2.18.7如何对接自定义Compose组件实现字幕实时显示?
ExoPlayer 2.18.7 自定义Compose字幕组件实现方案
核心思路
ExoPlayer 没有类似 MediaPlayer 的 onTimedTextListener,但可以通过**CueGroupListener**监听字幕更新,结合 Compose 的状态管理实现自定义字幕渲染。你之前尝试的onCues是正确方向,大概率是轨道配置或监听逻辑问题导致未生效。
步骤实现
1. 确保字幕轨道正确配置与激活
先确认SubtitleConfiguration已关联到MediaItem,并在用户开启字幕时激活对应轨道:
// 构建带字幕的MediaItem val subtitleConfig = SubtitleConfiguration.Builder(Uri.parse("subtitle_file_url")) .setMimeType(MimeTypes.TEXT_VTT) // 根据字幕格式设置对应MIME类型(如SRT用MimeTypes.APPLICATION_SUBRIP) .setLanguage("zh-CN") .build() val mediaItem = MediaItem.Builder() .setUri("audio_file_url") .setSubtitleConfigurations(listOf(subtitleConfig)) .build() player.setMediaItem(mediaItem) // 用户开启字幕时激活轨道 fun enableSubtitle() { val subtitleTrackGroups = player.currentTracks.groups.filter { it.type == C.TRACK_TYPE_TEXT } if (subtitleTrackGroups.isNotEmpty()) { val trackSelectionParams = player.trackSelectionParameters.buildUpon() .setTrackTypeDisabled(C.TRACK_TYPE_TEXT, false) // 启用字幕轨道类型 .setSelectedTextTrackIndex(subtitleTrackGroups[0].indexInTrackGroupArray) // 选中第一个字幕轨道 .build() player.trackSelectionParameters = trackSelectionParams } } // 用户关闭字幕时禁用 fun disableSubtitle() { val trackSelectionParams = player.trackSelectionParameters.buildUpon() .setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true) .build() player.trackSelectionParameters = trackSelectionParams }
2. 注册CueGroupListener监听字幕更新
通过addCueGroupListener获取实时字幕数据(Cue对象包含文本、显示时间范围等信息),并更新Compose状态:
// 在Compose中定义状态存储当前字幕 val currentSubtitleState = remember { mutableStateOf("") } val coroutineScope = rememberCoroutineScope() // 注册监听器(建议在player初始化后注册) player.addCueGroupListener { _, cues -> // 拼接所有字幕行,处理多行字幕场景 val subtitleText = cues.joinToString("\n") { cue -> cue.text?.toString() ?: "" } // 更新Compose状态,需在协程中操作 coroutineScope.launch { currentSubtitleState.value = subtitleText } }
3. 自定义Compose字幕组件
基于状态渲染自定义视图,根据用户的字幕开关控制显示:
@Composable fun CustomSubtitleView( currentSubtitle: String, isSubtitleEnabled: Boolean ) { if (isSubtitleEnabled && currentSubtitle.isNotEmpty()) { Box( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 32.dp) .align(Alignment.BottomCenter), contentAlignment = Alignment.Center ) { Text( text = currentSubtitle, color = Color.White, fontSize = 18.sp, style = TextStyle( background = Color.Black.copy(alpha = 0.7f), padding = PaddingValues(horizontal = 8.dp, vertical = 4.dp) ) ) } } } // 使用示例 CustomSubtitleView( currentSubtitle = currentSubtitleState.value, isSubtitleEnabled = remember { mutableStateOf(true) }.value )
常见问题排查
onCues未触发:检查字幕轨道是否被正确激活(通过player.currentTracks查看选中状态),或字幕文件的格式、路径是否正确。- 字幕乱码:确认
SubtitleConfiguration的MIME类型与字幕文件格式匹配。
内容的提问来源于stack exchange,提问作者Petermonteer
相关产品推荐
相关产品推荐

