Skip to content

Commit ba98cb8

Browse files
committed
optimize track select
1 parent 7db2ca3 commit ba98cb8

3 files changed

Lines changed: 64 additions & 61 deletions

File tree

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ android {
1717
applicationId = "com.donut.mixfile"
1818
minSdk = 26
1919
targetSdk = 36
20-
versionCode = 161
21-
versionName = "2.0.11.2"
20+
versionCode = 162
21+
versionName = "2.0.11.3"
2222

2323
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2424
vectorDrawables {

app/src/main/java/com/donut/mixfile/activity/video/player/PlayerUtils.kt

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -21,91 +21,92 @@ import androidx.compose.ui.unit.sp
2121
import androidx.media3.common.C
2222
import androidx.media3.common.TrackGroup
2323
import androidx.media3.common.TrackSelectionOverride
24-
import androidx.media3.common.Tracks
24+
import androidx.media3.common.util.UnstableApi
2525
import androidx.media3.exoplayer.ExoPlayer
2626
import com.donut.mixfile.ui.component.common.MixDialogBuilder
2727
import com.donut.mixfile.ui.component.common.SingleSelectItemList
28+
import java.util.Locale
2829

29-
object TrackUtils {
30-
/**
31-
* 获取格式化后的轨道列表,处理重复 Label
32-
*/
33-
fun getFormattedTracks(
34-
groups: List<Tracks.Group>,
35-
defaultPrefix: String = "轨道"
36-
): List<TrackInfo> {
37-
val options = mutableListOf<TrackInfo>()
38-
val labelCounter = mutableMapOf<String, Int>()
39-
40-
groups.forEach { group ->
41-
for (i in 0 until group.length) {
42-
val format = group.getTrackFormat(i)
43-
val baseLabel = format.label ?: format.language ?: defaultPrefix
44-
45-
val count = labelCounter.getOrDefault(baseLabel, 0) + 1
46-
labelCounter[baseLabel] = count
47-
val finalLabel = if (count > 1) "$baseLabel-$count" else baseLabel
48-
49-
options.add(
50-
TrackInfo(
51-
finalLabel,
52-
group.mediaTrackGroup,
53-
i,
54-
group.isSelected && group.isTrackSelected(i)
55-
)
56-
)
57-
}
58-
}
59-
return options
60-
}
61-
62-
data class TrackInfo(
63-
val label: String,
64-
val group: TrackGroup,
65-
val index: Int,
66-
val isSelected: Boolean
67-
)
68-
}
6930

7031
/**
7132
* 显示字幕/音轨选择弹窗
7233
*/
34+
@androidx.annotation.OptIn(UnstableApi::class)
7335
fun showTrackSelector(
7436
title: String,
7537
player: ExoPlayer,
7638
trackType: @C.TrackType Int,
7739
colorScheme: ColorScheme,
7840
hasDisableOption: Boolean = false
7941
) {
80-
// 只保留指定类型的 track group
42+
// 1. 获取所有轨道组并提取规范化信息
8143
val groups = player.currentTracks.groups.filter { it.type == trackType }
82-
val trackInfos = TrackUtils.getFormattedTracks(
83-
groups,
84-
if (trackType == C.TRACK_TYPE_TEXT) "字幕" else "音轨"
44+
45+
// 内部数据类,用于解耦逻辑
46+
data class TrackDisplayInfo(
47+
val label: String,
48+
val group: TrackGroup,
49+
val index: Int,
50+
val isSelected: Boolean
8551
)
8652

87-
// 构建选项列表
53+
var trackIndex = 1
54+
val trackInfos = groups.flatMap { group ->
55+
val trackGroup = group.mediaTrackGroup
56+
List(trackGroup.length) { i ->
57+
val format = trackGroup.getFormat(i)
58+
val langLabel = format.language?.let { lang ->
59+
val locale = Locale.forLanguageTag(lang)
60+
61+
locale.getDisplayName(Locale.getDefault()).ifBlank { format.language }
62+
} ?: "未知"
63+
64+
65+
val displayLabel = "${trackIndex} ${langLabel}".let {
66+
if (format.label != null) {
67+
it + " - ${format.label}"
68+
} else it
69+
}
70+
trackIndex++
71+
72+
73+
TrackDisplayInfo(
74+
label = displayLabel,
75+
group = trackGroup,
76+
index = i,
77+
isSelected = group.isTrackSelected(i)
78+
)
79+
}
80+
}
81+
82+
// 2. 构建 UI 选项列表
83+
val disableLabel = if (trackType == C.TRACK_TYPE_TEXT) "关闭字幕" else "禁用音轨"
8884
val options = buildList {
89-
if (hasDisableOption) add("关闭")
85+
if (hasDisableOption) add(disableLabel)
9086
addAll(trackInfos.map { it.label })
9187
}
9288

93-
// 获取当前选中的 label
94-
val currentLabel = trackInfos.firstOrNull { it.isSelected }?.label
95-
?: if (hasDisableOption) "关闭" else options.firstOrNull().orEmpty()
89+
val currentSelectedLabel = trackInfos.firstOrNull { it.isSelected }?.label ?: disableLabel
9690

9791
MixDialogBuilder(title, colorScheme = colorScheme).apply {
9892
setContent {
99-
SingleSelectItemList(options, currentOption = currentLabel) { selected ->
100-
val builder = player.trackSelectionParameters.buildUpon()
101-
if (selected == "关闭") {
102-
builder.setTrackTypeDisabled(trackType, true)
93+
SingleSelectItemList(options, currentOption = currentSelectedLabel) { selected ->
94+
val paramsBuilder = player.trackSelectionParameters.buildUpon()
95+
96+
if (selected == disableLabel) {
97+
paramsBuilder.setTrackTypeDisabled(trackType, true)
10398
} else {
104-
val info = trackInfos.first { it.label == selected }
105-
builder.setTrackTypeDisabled(trackType, false)
106-
.setOverrideForType(TrackSelectionOverride(info.group, info.index))
99+
val info = trackInfos.firstOrNull { it.label == selected }
100+
info?.let {
101+
paramsBuilder
102+
.setTrackTypeDisabled(trackType, false)
103+
// 清除该类型之前的覆盖设置,确保新设置生效
104+
.clearOverridesOfType(trackType)
105+
.addOverride(TrackSelectionOverride(it.group, it.index))
106+
}
107107
}
108-
player.trackSelectionParameters = builder.build()
108+
109+
player.trackSelectionParameters = paramsBuilder.build()
109110
closeDialog()
110111
}
111112
}

app/src/main/java/com/donut/mixfile/activity/video/player/PlayerView.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ fun VideoPlayerScreen(
8282

8383
}
8484

85-
8685
val extractorsFactory = DefaultExtractorsFactory().apply {
8786
// 开启对所有可能的容器支持
8887
setConstantBitrateSeekingEnabled(true) // 允许对没有索引的流进行粗略进度拖动
@@ -93,6 +92,9 @@ fun VideoPlayerScreen(
9392
.setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory))
9493
.build()
9594
.apply {
95+
trackSelectionParameters = trackSelectionParameters.buildUpon()
96+
.setPreferredTextLanguages("zh", "zh-CN", "zh-TW")
97+
.build()
9698
addListener(object : Player.Listener {
9799
override fun onPlayerError(error: PlaybackException) {
98100
showErrorDialog(error, "播放出错", playerColorScheme)

0 commit comments

Comments
 (0)