mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Better support for remote media (HLS/DASH) (#675)
## Description Check if playback is for a remote source and, if so, play that remote URL directly. Works for both ExoPlayer & MPV. Also adds support for direct playback for DASH in ExoPlayer. ### Related issues Closes #471 Closes #666
This commit is contained in:
parent
75a98ddaa5
commit
b78f5fcc77
5 changed files with 25 additions and 8 deletions
|
|
@ -199,6 +199,7 @@ dependencies {
|
||||||
implementation(libs.androidx.media3.session)
|
implementation(libs.androidx.media3.session)
|
||||||
implementation(libs.androidx.media3.datasource.okhttp)
|
implementation(libs.androidx.media3.datasource.okhttp)
|
||||||
implementation(libs.androidx.media3.exoplayer.hls)
|
implementation(libs.androidx.media3.exoplayer.hls)
|
||||||
|
implementation(libs.androidx.media3.exoplayer.dash)
|
||||||
implementation(libs.androidx.media3.ui)
|
implementation(libs.androidx.media3.ui)
|
||||||
implementation(libs.androidx.media3.ui.compose)
|
implementation(libs.androidx.media3.ui.compose)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.Format
|
import androidx.media3.common.Format
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.MimeTypes
|
||||||
import androidx.media3.common.PlaybackException
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.Tracks
|
import androidx.media3.common.Tracks
|
||||||
|
|
@ -46,6 +47,7 @@ import com.github.damontecres.wholphin.services.PlaylistCreationResult
|
||||||
import com.github.damontecres.wholphin.services.PlaylistCreator
|
import com.github.damontecres.wholphin.services.PlaylistCreator
|
||||||
import com.github.damontecres.wholphin.services.RefreshRateService
|
import com.github.damontecres.wholphin.services.RefreshRateService
|
||||||
import com.github.damontecres.wholphin.services.StreamChoiceService
|
import com.github.damontecres.wholphin.services.StreamChoiceService
|
||||||
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.onMain
|
import com.github.damontecres.wholphin.ui.onMain
|
||||||
|
|
@ -61,6 +63,7 @@ import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
||||||
import com.github.damontecres.wholphin.util.checkForSupport
|
import com.github.damontecres.wholphin.util.checkForSupport
|
||||||
import com.github.damontecres.wholphin.util.mpv.mpvDeviceProfile
|
import com.github.damontecres.wholphin.util.mpv.mpvDeviceProfile
|
||||||
|
import com.github.damontecres.wholphin.util.profile.Codec
|
||||||
import com.github.damontecres.wholphin.util.subtitleMimeTypes
|
import com.github.damontecres.wholphin.util.subtitleMimeTypes
|
||||||
import com.github.damontecres.wholphin.util.supportItemKinds
|
import com.github.damontecres.wholphin.util.supportItemKinds
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|
@ -604,13 +607,18 @@ class PlaybackViewModel
|
||||||
source?.let { source ->
|
source?.let { source ->
|
||||||
val mediaUrl =
|
val mediaUrl =
|
||||||
if (source.supportsDirectPlay) {
|
if (source.supportsDirectPlay) {
|
||||||
api.videosApi.getVideoStreamUrl(
|
if (source.isRemote && source.path.isNotNullOrBlank()) {
|
||||||
itemId = itemId,
|
Timber.i("Playback is remote for source: %s", source.id)
|
||||||
mediaSourceId = source.id,
|
source.path
|
||||||
static = true,
|
} else {
|
||||||
tag = source.eTag,
|
api.videosApi.getVideoStreamUrl(
|
||||||
playSessionId = response.playSessionId,
|
itemId = itemId,
|
||||||
)
|
mediaSourceId = source.id,
|
||||||
|
static = true,
|
||||||
|
tag = source.eTag,
|
||||||
|
playSessionId = response.playSessionId,
|
||||||
|
)
|
||||||
|
}
|
||||||
} else if (source.supportsDirectStream) {
|
} else if (source.supportsDirectStream) {
|
||||||
source.transcodingUrl?.let(api::createUrl)
|
source.transcodingUrl?.let(api::createUrl)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -663,7 +671,12 @@ class PlaybackViewModel
|
||||||
.setMediaId(itemId.toString())
|
.setMediaId(itemId.toString())
|
||||||
.setUri(mediaUrl.toUri())
|
.setUri(mediaUrl.toUri())
|
||||||
.setSubtitleConfigurations(listOfNotNull(externalSubtitle))
|
.setSubtitleConfigurations(listOfNotNull(externalSubtitle))
|
||||||
.build()
|
.apply {
|
||||||
|
when (source.container) {
|
||||||
|
Codec.Container.HLS -> setMimeType(MimeTypes.APPLICATION_M3U8)
|
||||||
|
Codec.Container.DASH -> setMimeType(MimeTypes.APPLICATION_MPD)
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
|
||||||
val playback =
|
val playback =
|
||||||
CurrentPlayback(
|
CurrentPlayback(
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ object Codec {
|
||||||
const val `3GP` = "3gp"
|
const val `3GP` = "3gp"
|
||||||
const val ASF = "asf"
|
const val ASF = "asf"
|
||||||
const val AVI = "avi"
|
const val AVI = "avi"
|
||||||
|
const val DASH = "dash"
|
||||||
const val DVR_MS = "dvr-ms"
|
const val DVR_MS = "dvr-ms"
|
||||||
const val HLS = "hls"
|
const val HLS = "hls"
|
||||||
const val M2V = "m2v"
|
const val M2V = "m2v"
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ fun createDeviceProfile(
|
||||||
|
|
||||||
container(
|
container(
|
||||||
Codec.Container.ASF,
|
Codec.Container.ASF,
|
||||||
|
Codec.Container.DASH,
|
||||||
Codec.Container.HLS,
|
Codec.Container.HLS,
|
||||||
Codec.Container.M4V,
|
Codec.Container.M4V,
|
||||||
Codec.Container.MKV,
|
Codec.Container.MKV,
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ androidx-media3-datasource-okhttp = { module = "androidx.media3:media3-datasourc
|
||||||
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "androidx-media3" }
|
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "androidx-media3" }
|
||||||
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "androidx-media3" }
|
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "androidx-media3" }
|
||||||
androidx-media3-exoplayer-hls = { module = "androidx.media3:media3-exoplayer-hls", version.ref = "androidx-media3" }
|
androidx-media3-exoplayer-hls = { module = "androidx.media3:media3-exoplayer-hls", version.ref = "androidx-media3" }
|
||||||
|
androidx-media3-exoplayer-dash = { module = "androidx.media3:media3-exoplayer-dash", version.ref = "androidx-media3" }
|
||||||
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "androidx-media3" }
|
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "androidx-media3" }
|
||||||
androidx-media3-ui-compose = { module = "androidx.media3:media3-ui-compose", version.ref = "androidx-media3" }
|
androidx-media3-ui-compose = { module = "androidx.media3:media3-ui-compose", version.ref = "androidx-media3" }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue