Skip to content

Commit 5d71dbc

Browse files
committed
feat: improve track selection with manifest support and fix language auto-picking
1 parent 4d7d8eb commit 5d71dbc

3 files changed

Lines changed: 79 additions & 10 deletions

File tree

app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ShortView.kt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ class ShortView : FrameLayout {
580580
}.toList().toTypedArray()
581581
)
582582
else null, if (bestAudioSources.isNotEmpty()) SlideUpMenuGroup(
583-
this.context, context.getString(R.string.audio), "audio", *bestAudioSources.map {
583+
this.context, context.getString(R.string.audio), "audio", *(bestAudioSources.map {
584584
val estSize = VideoHelper.estimateSourceSize(it)
585585
val prefix = if (estSize > 0) "±" + estSize.toHumanBytesSize() + " " else ""
586586
SlideUpMenuItem(this.context, R.drawable.ic_music, it.name, it.bitrate.toHumanBitrate(), (prefix + it.codec.trim()).trim(), tag = it, call = { handleSelectAudioTrack(it) }).apply {
@@ -590,7 +590,20 @@ class ShortView : FrameLayout {
590590
this.visibility = View.GONE
591591
}
592592
}
593-
}.toList().toTypedArray()
593+
}.toList() + (
594+
player.exoPlayer?.player?.currentTracks?.groups?.filter { it.mediaTrackGroup.type == C.TRACK_TYPE_AUDIO }?.flatMap { group ->
595+
(0 until group.mediaTrackGroup.length).map { i ->
596+
val format = group.mediaTrackGroup.getFormat(i);
597+
SlideUpMenuItem(this.context, R.drawable.ic_music, format.label ?: format.id ?: "Track $i", format.bitrate.toHumanBitrate(), format.language ?: "", tag = format, call = { player.selectAudioTrack(format) }).apply {
598+
audioSourceItems.add(this);
599+
if (selectedLanguage != null) {
600+
if (format.language != selectedLanguage)
601+
this.visibility = View.GONE;
602+
}
603+
}
604+
}
605+
} ?: listOf()
606+
)).toTypedArray()
594607
)
595608
else null, if (video?.subtitles?.isNotEmpty() == true) SlideUpMenuGroup(
596609
this.context, context.getString(R.string.subtitles), "subtitles", *video.subtitles.map {
@@ -935,6 +948,10 @@ class ShortView : FrameLayout {
935948
?: player.getPreferredAudioSource(videoDetails, Settings.instance.playback.getPrimaryLanguage(context))
936949
val subtitleSource = _lastSubtitleSource
937950
?: (if (videoDetails is VideoLocal) videoDetails.subtitlesSources.firstOrNull() else null)
951+
952+
player.setPreferredAudioLanguage(Settings.instance.playback.getPrimaryLanguage(context));
953+
player.setPreferredSubtitleLanguage(null); // Shorts usually don't have sticky subtitles in the same way
954+
938955
Logger.i(TAG, "loadCurrentVideo(videoSource=$videoSource, audioSource=$audioSource, subtitleSource=$subtitleSource, resumePositionMs=$resumePositionMs)")
939956

940957
if (videoSource == null && audioSource == null) {

app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,7 +2666,7 @@ class VideoDetailView : ConstraintLayout {
26662666
else null,
26672667
if(bestAudioSources.isNotEmpty())
26682668
SlideUpMenuGroup(this.context, context.getString(R.string.audio), "audio",
2669-
*bestAudioSources
2669+
*(bestAudioSources
26702670
.map {
26712671
val estSize = VideoHelper.estimateSourceSize(it);
26722672
val prefix = if(estSize > 0) "±" + estSize.toHumanBytesSize() + " " else "";
@@ -2683,7 +2683,20 @@ class VideoDetailView : ConstraintLayout {
26832683
this.visibility = View.GONE;
26842684
}
26852685
}
2686-
}.toList().toTypedArray())
2686+
}.toList() + (
2687+
_player.exoPlayer?.player?.currentTracks?.groups?.filter { it.mediaTrackGroup.type == C.TRACK_TYPE_AUDIO }?.flatMap { group ->
2688+
(0 until group.mediaTrackGroup.length).map { i ->
2689+
val format = group.mediaTrackGroup.getFormat(i);
2690+
SlideUpMenuItem(this.context, R.drawable.ic_music, format.label ?: format.id ?: "Track $i", format.bitrate.toHumanBitrate(), format.language ?: "", tag = format, call = { _player.selectAudioTrack(format) }).apply {
2691+
audioSourceItems.add(this);
2692+
if (selectedLanguage != null) {
2693+
if (format.language != selectedLanguage)
2694+
this.visibility = View.GONE;
2695+
}
2696+
}
2697+
}
2698+
} ?: listOf()
2699+
)).toTypedArray())
26872700
else null,
26882701
if(video?.subtitles?.isNotEmpty() == true)
26892702
SlideUpMenuGroup(this.context, context.getString(R.string.subtitles), "subtitles",

app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import androidx.media3.common.C
1717
import androidx.media3.common.MediaItem
1818
import androidx.media3.common.PlaybackException
1919
import androidx.media3.common.Player
20+
import androidx.media3.common.TrackSelectionOverride
2021
import androidx.media3.common.VideoSize
2122
import androidx.media3.common.text.CueGroup
2223
import androidx.media3.common.util.UnstableApi
@@ -147,6 +148,8 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
147148
var targetTrackVideoHeight = -1
148149
private set
149150
private var _targetTrackAudioBitrate = -1
151+
private var _targetTrackVideoFormat: Format? = null;
152+
private var _targetTrackAudioFormat: Format? = null;
150153
var preferredAudioLanguage: String? = null
151154
private set;
152155
var preferredSubtitleLanguage: String? = null
@@ -328,10 +331,22 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
328331
//TODO: Temporary solution, Implement custom track selector without using constraints
329332
fun selectVideoTrack(height: Int) {
330333
targetTrackVideoHeight = height;
334+
_targetTrackVideoFormat = null;
335+
updateTrackSelector();
336+
}
337+
fun selectVideoTrack(format: Format?) {
338+
_targetTrackVideoFormat = format;
339+
targetTrackVideoHeight = format?.height ?: -1;
331340
updateTrackSelector();
332341
}
333342
fun selectAudioTrack(bitrate: Int) {
334343
_targetTrackAudioBitrate = bitrate;
344+
_targetTrackAudioFormat = null;
345+
updateTrackSelector();
346+
}
347+
fun selectAudioTrack(format: Format?) {
348+
_targetTrackAudioFormat = format;
349+
_targetTrackAudioBitrate = format?.bitrate ?: -1;
335350
updateTrackSelector();
336351
}
337352
fun setPreferredAudioLanguage(lang: String?) {
@@ -345,15 +360,43 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
345360

346361
@OptIn(UnstableApi::class)
347362
private fun updateTrackSelector() {
348-
var builder = DefaultTrackSelector.Parameters.Builder(context);
363+
var builder = (exoPlayer?.player?.trackSelectionParameters as? DefaultTrackSelector.Parameters)?.buildUpon()
364+
?: DefaultTrackSelector.Parameters.Builder(context);
365+
366+
builder = builder.clearOverrides();
367+
368+
if (_targetTrackVideoFormat != null || _targetTrackAudioFormat != null) {
369+
val tracks = exoPlayer?.player?.currentTracks;
370+
if (tracks != null) {
371+
if (_targetTrackVideoFormat != null) {
372+
val group = tracks.groups.find { it.mediaTrackGroup.type == C.TRACK_TYPE_VIDEO && (0 until it.mediaTrackGroup.length).any { i -> it.mediaTrackGroup.getFormat(i) == _targetTrackVideoFormat } };
373+
if (group != null) {
374+
builder = builder.addOverride(TrackSelectionOverride(group.mediaTrackGroup, (0 until group.mediaTrackGroup.length).find { i -> group.mediaTrackGroup.getFormat(i) == _targetTrackVideoFormat }!!));
375+
}
376+
}
377+
if (_targetTrackAudioFormat != null) {
378+
val group = tracks.groups.find { it.mediaTrackGroup.type == C.TRACK_TYPE_AUDIO && (0 until it.mediaTrackGroup.length).any { i -> it.mediaTrackGroup.getFormat(i) == _targetTrackAudioFormat } };
379+
if (group != null) {
380+
builder = builder.addOverride(TrackSelectionOverride(group.mediaTrackGroup, (0 until group.mediaTrackGroup.length).find { i -> group.mediaTrackGroup.getFormat(i) == _targetTrackAudioFormat }!!));
381+
}
382+
}
383+
}
384+
}
385+
349386
if(targetTrackVideoHeight > 0) {
350387
builder = builder
351388
.setMinVideoSize(0, targetTrackVideoHeight - 10)
352389
.setMaxVideoSize(9999, targetTrackVideoHeight + 10);
390+
} else {
391+
builder = builder
392+
.setMinVideoSize(0, 0)
393+
.setMaxVideoSize(9999, 9999);
353394
}
354395

355396
if(_targetTrackAudioBitrate > 0) {
356397
builder = builder.setMaxAudioBitrate(_targetTrackAudioBitrate);
398+
} else {
399+
builder = builder.setMaxAudioBitrate(Int.MAX_VALUE);
357400
}
358401

359402
if (preferredAudioLanguage != null) {
@@ -363,11 +406,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
363406
builder = builder.setPreferredTextLanguage(preferredSubtitleLanguage);
364407
}
365408

366-
builder = if (isAudioMode) {
367-
builder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, true)
368-
} else {
369-
builder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, false)
370-
}
409+
builder = builder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioMode);
371410

372411
val trackSelector = exoPlayer?.player?.trackSelector;
373412
if(trackSelector != null) {

0 commit comments

Comments
 (0)