ExoPlayer 内嵌字幕显示指南:自动与手动选择
2025-01-13 01:51:21
ExoPlayer 展示内嵌字幕
视频播放时,内嵌字幕是一种常见需求。通常,视频文件本身就包含字幕数据,无需额外字幕文件。此文将介绍如何使用 ExoPlayer 显示这些内嵌字幕。
问题分析
ExoPlayer
可以处理多种字幕格式,包括外挂字幕和内嵌字幕。对于外挂字幕,像文章开头提供的代码那样配置 SubtitleConfiguration
即可。对于内嵌字幕,播放器会自动检测并尝试解码。问题的关键在于,默认情况下,ExoPlayer
可能没有启用对所有可用内嵌字幕轨道的自动选择。
解决方案一:启用默认字幕轨道选择
一个简单的办法是告诉 ExoPlayer
选择默认的字幕轨道。这通过调整 DefaultTrackSelector
的行为来实现。DefaultTrackSelector
负责决定选择哪个音视频和字幕轨道。
以下步骤和代码演示如何操作:
- 创建
DefaultTrackSelector
并配置其参数。allowVideoMixedMimeTypeAdaptiveness
用于设置混合编码自适应的规则。 - 实例化
ExoPlayer
时,将配置过的TrackSelector
传递进去。这样ExoPlayer
就知道了应如何选择合适的音视频和字幕轨道。
val trackSelector = DefaultTrackSelector(context).apply {
parameters = buildUponParameters()
.setRendererDisabled(C.TRACK_TYPE_TEXT, false) //确保字幕渲染器未禁用
.setAllowVideoMixedMimeTypeAdaptiveness(true) // 如果存在,启用视频自适应。 这取决于情况
.setSelectionOverride(0, C.TRACK_TYPE_TEXT, null).build()
}
val player = ExoPlayer.Builder(context)
.setTrackSelector(trackSelector)
.build()
player.setMediaItem(MediaItem.fromUri(videoUri))
player.prepare()
player.play()
此处 setRendererDisabled(C.TRACK_TYPE_TEXT, false)
非常关键,确保字幕渲染器不被禁用。setSelectionOverride(0, C.TRACK_TYPE_TEXT, null)
,表示选择索引为 0,且类型为TEXT
的字幕轨道。 这会在无首选语言的情况下强制执行。
通过这些步骤,ExoPlayer
大概率会自动选择合适的字幕轨道。
解决方案二:显式选择字幕轨道
有时自动选择不能满足需要。如果想控制选择特定语言的字幕,或当有多个字幕轨道时进行手动选择,可以使用 Player.getCurrentTracks()
方法获取当前媒体的所有可用轨道,并显式选择特定字幕轨道。
操作步骤如下:
- 获取当前媒体的
Tracks
对象。使用player.getCurrentTracks()
获取Tracks
实例,并通过循环遍历获取字幕轨道的信息。 - 过滤出
TRACK_TYPE_TEXT
的轨道并展示可用字幕的列表,可以选择使用对话框或是其它展示形式。 - 当用户选择了目标字幕,则使用
trackSelectionParameters
强制ExoPlayer
选择对应的字幕轨道。
val mappedTrackInfo = player.currentTracksInfo
for (group in mappedTrackInfo.trackGroupInfos) {
val trackGroup = group.mediaTrackGroup
for(i in 0 until trackGroup.length){
val trackFormat = trackGroup.getFormat(i)
if(MimeTypes.isText(trackFormat.sampleMimeType)){
// 在这里展示轨道信息
Log.d(TAG, "Track found:${trackFormat.language} id: $i mimeType:${trackFormat.sampleMimeType}")
// 假设现在要选英文 (根据需要选择其它字幕,例如根据id选择)
if("eng" == trackFormat.language){
val trackSelector = DefaultTrackSelector(context)
val override = MappingTrackSelector.SelectionOverride(i, C.FORMAT_HANDLED)
trackSelector.parameters = trackSelector.buildUponParameters()
.setSelectionOverride(0,C.TRACK_TYPE_TEXT,override) // 0: Media Track Group index;
.build()
player.trackSelectionParameters = trackSelector.parameters
break; //找到目标就跳出,实际项目中需谨慎
}
}
}
}
这段代码示例说明了如何在多个字幕轨道中根据语言选择字幕。关键是通过 setSelectionOverride
方法配置 TrackSelector
参数,实现指定字幕轨道的选取。代码里的 if("eng" == trackFormat.language)
可以按实际的业务需求更改。需要指出的是 SelectionOverride
参数的第一个 int 类型的参数表示 trackGroup 在集合 TrackGroupInfo
里的索引位置, 可以设置 0 或者从实际的情况进行选择,该参数非常关键,设置不当会出现 IllegalArgumentException: trackGroupIndex invalid:
的错误。
总结
这两种方案都能解决在 ExoPlayer 中展示内嵌字幕的问题。第一种方法简洁,依赖 ExoPlayer 的自动选择逻辑。第二种方法更加灵活,可用于处理复杂场景或需要手动选择的情况。具体采用哪种,取决于项目的需求和对字幕控制的精细程度。选用时需综合考虑。务必确保正确设置了 DefaultTrackSelector
的相关参数,以防止出现字幕轨道被忽略的情况。同时需注意处理好多语言支持和无字幕轨道的情况。