mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Fallback to transcoding if direct play fails (#79)
If direct playing (or direct streaming) fails on device, attempt to fall back to transcoding. Also display more error information if available
This commit is contained in:
parent
07a0db8e98
commit
c4df751918
2 changed files with 62 additions and 9 deletions
|
|
@ -42,6 +42,19 @@ fun ErrorMessage(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var cause = exception?.cause
|
||||||
|
while (cause != null) {
|
||||||
|
cause.localizedMessage?.let {
|
||||||
|
item {
|
||||||
|
Text(
|
||||||
|
text = "Caused by: $it",
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cause = cause.cause
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -367,6 +367,8 @@ class PlaybackViewModel
|
||||||
subtitleIndex: Int?,
|
subtitleIndex: Int?,
|
||||||
positionMs: Long = C.TIME_UNSET,
|
positionMs: Long = C.TIME_UNSET,
|
||||||
userInitiated: Boolean,
|
userInitiated: Boolean,
|
||||||
|
enableDirectPlay: Boolean = true,
|
||||||
|
enableDirectStream: Boolean = true,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
val itemId = item.id
|
val itemId = item.id
|
||||||
|
|
||||||
|
|
@ -380,7 +382,10 @@ class PlaybackViewModel
|
||||||
// Timber.i("No change in playback for changeStreams")
|
// Timber.i("No change in playback for changeStreams")
|
||||||
// return@withContext
|
// return@withContext
|
||||||
// }
|
// }
|
||||||
Timber.d("changeStreams: userInitiated=$userInitiated, audioIndex=$audioIndex, subtitleIndex=$subtitleIndex")
|
Timber.d(
|
||||||
|
"changeStreams: userInitiated=$userInitiated, audioIndex=$audioIndex, subtitleIndex=$subtitleIndex, " +
|
||||||
|
"enableDirectPlay=$enableDirectPlay, enableDirectStream=$enableDirectStream",
|
||||||
|
)
|
||||||
|
|
||||||
// TODO if the new audio or subtitle index is already in the streams (eg direct play), should toggle in the player instead
|
// TODO if the new audio or subtitle index is already in the streams (eg direct play), should toggle in the player instead
|
||||||
val maxBitrate =
|
val maxBitrate =
|
||||||
|
|
@ -393,17 +398,18 @@ class PlaybackViewModel
|
||||||
PlaybackInfoDto(
|
PlaybackInfoDto(
|
||||||
startTimeTicks = null,
|
startTimeTicks = null,
|
||||||
deviceProfile = deviceProfile,
|
deviceProfile = deviceProfile,
|
||||||
enableDirectPlay = true,
|
|
||||||
enableDirectStream = true,
|
|
||||||
maxAudioChannels = null,
|
maxAudioChannels = null,
|
||||||
audioStreamIndex = audioIndex,
|
audioStreamIndex = audioIndex,
|
||||||
subtitleStreamIndex = subtitleIndex,
|
subtitleStreamIndex = subtitleIndex,
|
||||||
allowVideoStreamCopy = true,
|
|
||||||
allowAudioStreamCopy = true,
|
|
||||||
autoOpenLiveStream = true,
|
|
||||||
mediaSourceId = currentItemPlayback.sourceId?.toServerString(),
|
mediaSourceId = currentItemPlayback.sourceId?.toServerString(),
|
||||||
alwaysBurnInSubtitleWhenTranscoding = null,
|
alwaysBurnInSubtitleWhenTranscoding = null,
|
||||||
maxStreamingBitrate = maxBitrate.toInt(),
|
maxStreamingBitrate = maxBitrate.toInt(),
|
||||||
|
enableDirectPlay = enableDirectPlay,
|
||||||
|
enableDirectStream = enableDirectStream,
|
||||||
|
allowVideoStreamCopy = enableDirectStream,
|
||||||
|
allowAudioStreamCopy = enableDirectStream,
|
||||||
|
enableTranscoding = true,
|
||||||
|
autoOpenLiveStream = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if (response.errorCode != null) {
|
if (response.errorCode != null) {
|
||||||
|
|
@ -422,10 +428,16 @@ class PlaybackViewModel
|
||||||
playSessionId = response.playSessionId,
|
playSessionId = response.playSessionId,
|
||||||
)
|
)
|
||||||
} else if (source.supportsDirectStream) {
|
} else if (source.supportsDirectStream) {
|
||||||
api.createUrl(source.transcodingUrl!!)
|
source.transcodingUrl?.let(api::createUrl)
|
||||||
} else {
|
} else {
|
||||||
api.createUrl(source.transcodingUrl!!)
|
source.transcodingUrl?.let(api::createUrl)
|
||||||
}
|
}
|
||||||
|
if (mediaUrl.isNullOrBlank()) {
|
||||||
|
loading.setValueOnMain(
|
||||||
|
LoadingState.Error("Unable to get media URL from the server. Do you have permission to view and/or transcode?"),
|
||||||
|
)
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
val transcodeType =
|
val transcodeType =
|
||||||
when {
|
when {
|
||||||
source.supportsDirectPlay -> PlayMethod.DIRECT_PLAY
|
source.supportsDirectPlay -> PlayMethod.DIRECT_PLAY
|
||||||
|
|
@ -745,7 +757,35 @@ class PlaybackViewModel
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
Timber.e(error, "Playback error")
|
Timber.e(error, "Playback error")
|
||||||
viewModelScope.launch(Dispatchers.Main + ExceptionHandler()) {
|
viewModelScope.launch(Dispatchers.Main + ExceptionHandler()) {
|
||||||
loading.value = LoadingState.Error("Error during playback", error)
|
currentPlayback.value?.let {
|
||||||
|
when (it.playMethod) {
|
||||||
|
PlayMethod.TRANSCODE ->
|
||||||
|
loading.setValueOnMain(
|
||||||
|
LoadingState.Error(
|
||||||
|
"Error during playback",
|
||||||
|
error,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
PlayMethod.DIRECT_STREAM, PlayMethod.DIRECT_PLAY -> {
|
||||||
|
Timber.w("Playback error during ${it.playMethod}, falling back to transcoding")
|
||||||
|
changeStreams(
|
||||||
|
dto,
|
||||||
|
currentItemPlayback.value!!,
|
||||||
|
currentItemPlayback.value?.audioIndex,
|
||||||
|
currentItemPlayback.value?.subtitleIndex,
|
||||||
|
player.currentPosition,
|
||||||
|
false,
|
||||||
|
enableDirectPlay = false,
|
||||||
|
enableDirectStream = false,
|
||||||
|
)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
player.prepare()
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue