diff --git a/app/src/main/kotlin/com/subtracks/data/prefs/UserPreferences.kt b/app/src/main/kotlin/com/subtracks/data/prefs/UserPreferences.kt index 0c612de9..df38dab1 100644 --- a/app/src/main/kotlin/com/subtracks/data/prefs/UserPreferences.kt +++ b/app/src/main/kotlin/com/subtracks/data/prefs/UserPreferences.kt @@ -38,7 +38,9 @@ data class ListQuery( data class StreamQuality( val maxBitrate: Int = 0, val format: String? = null, -) +) { + val transcodes: Boolean get() = maxBitrate > 0 || !format.isNullOrEmpty() +} private val Context.preferences: DataStore by preferencesDataStore("user_prefs") diff --git a/app/src/main/kotlin/com/subtracks/data/source/StreamLength.kt b/app/src/main/kotlin/com/subtracks/data/source/StreamLength.kt index a58bcf06..67f3b236 100644 --- a/app/src/main/kotlin/com/subtracks/data/source/StreamLength.kt +++ b/app/src/main/kotlin/com/subtracks/data/source/StreamLength.kt @@ -13,7 +13,7 @@ fun declaredStreamLength( quality: StreamQuality, ): Long? { if (durationMs == null || durationMs <= 0) return null - if (quality.maxBitrate <= 0 && quality.format.isNullOrEmpty()) return null + if (!quality.transcodes) return null val bps = if (quality.maxBitrate > 0) maxOf(quality.maxBitrate * 1000L, MIN_TRANSCODE_BPS) else UNCAPPED_BPS return durationMs / 1000 * bps / 8 * 5 / 4 + OVERHEAD_BYTES } diff --git a/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt b/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt index 65e96280..30e66feb 100644 --- a/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt +++ b/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.util.Log import androidx.media3.common.C import androidx.media3.common.MediaItem +import androidx.media3.common.MediaItem.ClippingConfiguration import androidx.media3.common.MediaMetadata import androidx.media3.common.PlaybackException import androidx.media3.common.Player @@ -142,12 +143,20 @@ class Media3PlayerHandle( item.durationMs?.let { putLong(EXTRA_DURATION_MS, it) } }, ).build() - return MediaItem - .Builder() - .setMediaId(item.id) - .setUri(sourceRepository.streamUri(item.id, item.durationMs)) - .setMediaMetadata(metadata) - .build() + val builder = + MediaItem + .Builder() + .setMediaId(item.id) + .setUri(sourceRepository.streamUri(item.id, item.durationMs)) + .setMediaMetadata(metadata) + if (sourceRepository.quality.value.transcodes) { + item.durationMs?.takeIf { it > 0 }?.let { duration -> + builder.setClippingConfiguration( + ClippingConfiguration.Builder().setEndPositionMs(duration).build(), + ) + } + } + return builder.build() } private fun toQueueItem(mediaItem: MediaItem): QueueItem = diff --git a/app/src/main/kotlin/com/subtracks/playback/PlaybackService.kt b/app/src/main/kotlin/com/subtracks/playback/PlaybackService.kt index fdf5b8d7..4149a5c0 100644 --- a/app/src/main/kotlin/com/subtracks/playback/PlaybackService.kt +++ b/app/src/main/kotlin/com/subtracks/playback/PlaybackService.kt @@ -9,6 +9,7 @@ import androidx.media3.common.AudioAttributes import androidx.media3.common.C import androidx.media3.common.ForwardingPlayer import androidx.media3.common.Player +import androidx.media3.common.util.ExperimentalApi import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.exoplayer.ExoPlayer @@ -25,7 +26,7 @@ class PlaybackService : MediaSessionService() { private var session: MediaSession? = null private var artworkLoader: CoverArtBitmapLoader? = null - @OptIn(UnstableApi::class) + @OptIn(UnstableApi::class, ExperimentalApi::class) override fun onCreate() { super.onCreate() val exoPlayer = @@ -40,9 +41,11 @@ class PlaybackService : MediaSessionService() { true, ).setHandleAudioBecomingNoisy(true) .setMediaSourceFactory( - DefaultMediaSourceFactory(this).setDataSourceFactory( - KnownLengthDataSourceFactory(OkHttpDataSource.Factory(streamingClient())), - ), + DefaultMediaSourceFactory(this) + .setEnableClippingInMediaPeriod(true) + .setDataSourceFactory( + KnownLengthDataSourceFactory(OkHttpDataSource.Factory(streamingClient())), + ), ).build() val player = MetadataDurationPlayer(exoPlayer) val loader =