mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-06 02:40:58 +01:00
Fix issues with external subtitles & transcoding (#1790)
## Description Fixes a bug where the external subtitle track would not be activated if playback is transcoded Also fixes a bug where external subtitles would cause MPV to incorrectly switch to transcoding ### Related issues Fixes #1778 ### Testing Emulator with files that have a variety of external SRT, embedded SRT & ASS, & embedded PGS ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
7581b189aa
commit
454c0212b6
2 changed files with 93 additions and 41 deletions
|
|
@ -184,6 +184,7 @@ class PlaybackViewModel
|
|||
internal lateinit var currentItem: PlaylistItem
|
||||
internal var forceTranscoding: Boolean = false
|
||||
private var activityListener: TrackActivityPlaybackListener? = null
|
||||
private var trackChangeListener: TracksChangedListener? = null
|
||||
private val jobs = mutableListOf<Job>()
|
||||
|
||||
private val isPlaylist = destination is Destination.PlaybackList
|
||||
|
|
@ -215,6 +216,9 @@ class PlaybackViewModel
|
|||
it.release()
|
||||
player.removeListener(it)
|
||||
}
|
||||
this@PlaybackViewModel.trackChangeListener?.let {
|
||||
player.removeListener(it)
|
||||
}
|
||||
player.release()
|
||||
mediaSession?.release()
|
||||
}
|
||||
|
|
@ -604,6 +608,9 @@ class PlaybackViewModel
|
|||
withContext(WholphinDispatchers.IO) {
|
||||
val itemId = item.id
|
||||
|
||||
trackChangeListener?.let { onMain { player.removeListener(it) } }
|
||||
trackChangeListener = null
|
||||
|
||||
state.value.currentPlayback?.let { currentPlayback ->
|
||||
if (currentPlayback.item.id == item.id &&
|
||||
currentPlayback.playMethod == PlayMethod.DIRECT_PLAY &&
|
||||
|
|
@ -715,6 +722,7 @@ class PlaybackViewModel
|
|||
|
||||
val externalSubtitle =
|
||||
source.findExternalSubtitle(subtitleIndex)?.let {
|
||||
Timber.v("Using externally delivered subtitle tracks %s", subtitleIndex)
|
||||
it.deliveryUrl?.let { deliveryUrl ->
|
||||
var flags = 0
|
||||
if (it.isForced) flags = flags.or(C.SELECTION_FLAG_FORCED)
|
||||
|
|
@ -807,48 +815,51 @@ class PlaybackViewModel
|
|||
mediaItem,
|
||||
positionMs,
|
||||
)
|
||||
if (transcodeType == PlayMethod.DIRECT_PLAY && (audioIndex != null || subtitleIndex != null)) {
|
||||
val onTracksChangedListener =
|
||||
object : Player.Listener {
|
||||
override fun onTracksChanged(tracks: Tracks) {
|
||||
Timber.v("onTracksChanged: $tracks")
|
||||
if (tracks.groups.isNotEmpty()) {
|
||||
val result =
|
||||
TrackSelectionUtils.createTrackSelections(
|
||||
player.trackSelectionParameters,
|
||||
player.currentTracks,
|
||||
audioIndex,
|
||||
subtitleIndex,
|
||||
source,
|
||||
)
|
||||
Timber.v("onTracksChanged: %s", result)
|
||||
player.removeListener(this)
|
||||
if (result.bothSelected) {
|
||||
player.trackSelectionParameters =
|
||||
result.trackSelectionParameters
|
||||
} else {
|
||||
// Fall back to transcoding
|
||||
Timber.w(
|
||||
"Failed to select tracks, falling back to transcoding: %s",
|
||||
result,
|
||||
)
|
||||
viewModelScope.launchIO {
|
||||
changeStreams(
|
||||
item = item,
|
||||
sourceId = sourceId,
|
||||
audioIndex = audioIndex,
|
||||
subtitleIndex = subtitleIndex,
|
||||
positionMs = positionMs,
|
||||
enableDirectPlay = false,
|
||||
enableDirectStream = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
viewModelScope.launchIO { loadSubtitleDelay() }
|
||||
}
|
||||
}
|
||||
val onFailure: () -> Unit = {
|
||||
if (player is MpvPlayer && externalSubtitle != null) {
|
||||
// MpvPlayer may change tracks more than once to add external subtitles
|
||||
trackChangeListener?.let { player.addListener(it) }
|
||||
} else {
|
||||
viewModelScope.launchIO {
|
||||
changeStreams(
|
||||
item = item,
|
||||
sourceId = sourceId,
|
||||
audioIndex = audioIndex,
|
||||
subtitleIndex = subtitleIndex,
|
||||
positionMs = positionMs,
|
||||
enableDirectPlay = false,
|
||||
enableDirectStream = true,
|
||||
)
|
||||
}
|
||||
player.addListener(onTracksChangedListener)
|
||||
}
|
||||
}
|
||||
val onTracksChangedListener =
|
||||
if (transcodeType == PlayMethod.DIRECT_PLAY && (audioIndex != null || subtitleIndex != null)) {
|
||||
TracksChangedListener(
|
||||
player = player,
|
||||
audioIndex = audioIndex,
|
||||
subtitleIndex = subtitleIndex,
|
||||
source = source,
|
||||
onFailure = onFailure,
|
||||
)
|
||||
} else if (externalSubtitle != null) {
|
||||
TracksChangedListener(
|
||||
player = player,
|
||||
audioIndex = null, // Do not manually activate audio
|
||||
subtitleIndex = subtitleIndex,
|
||||
source = source,
|
||||
onFailure = onFailure,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
onTracksChangedListener?.let {
|
||||
player.addListener(it)
|
||||
this@PlaybackViewModel.trackChangeListener = it
|
||||
}
|
||||
|
||||
if (subtitleIndex != null) {
|
||||
viewModelScope.launchIO { loadSubtitleDelay() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.github.damontecres.wholphin.ui.playback
|
||||
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Tracks
|
||||
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||
import timber.log.Timber
|
||||
|
||||
class TracksChangedListener(
|
||||
val player: Player,
|
||||
val audioIndex: Int?,
|
||||
val subtitleIndex: Int?,
|
||||
val source: MediaSourceInfo,
|
||||
val onFailure: () -> Unit,
|
||||
) : Player.Listener {
|
||||
override fun onTracksChanged(tracks: Tracks) {
|
||||
Timber.v("onTracksChanged: $tracks")
|
||||
if (tracks.groups.isNotEmpty()) {
|
||||
val result =
|
||||
TrackSelectionUtils.createTrackSelections(
|
||||
player.trackSelectionParameters,
|
||||
player.currentTracks,
|
||||
audioIndex,
|
||||
subtitleIndex,
|
||||
source,
|
||||
)
|
||||
Timber.v("onTracksChanged: %s", result)
|
||||
player.removeListener(this)
|
||||
if (result.bothSelected) {
|
||||
player.trackSelectionParameters =
|
||||
result.trackSelectionParameters
|
||||
} else {
|
||||
// Fall back to transcoding
|
||||
Timber.w(
|
||||
"Failed to select tracks, falling back to transcoding: %s",
|
||||
result,
|
||||
)
|
||||
onFailure.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue