add yt test video

This commit is contained in:
Christian Schabesberger 2024-09-14 11:53:39 +02:00
parent edc720590c
commit 2fee9e59f6
8 changed files with 108 additions and 10 deletions

View File

@ -38,7 +38,13 @@ data class StreamVariant(
val streamType: StreamType, val streamType: StreamType,
val language: String?, val language: String?,
val streamVariantIdentifier: String val streamVariantIdentifier: String
) ) {
override fun equals(other: Any?) =
other is StreamVariant
&& other.streamType == streamType
&& other.language == language
&& other.streamVariantIdentifier == streamVariantIdentifier
}
data class RepoMetaInfo( data class RepoMetaInfo(
val canHandleTimestampedLinks: Boolean, val canHandleTimestampedLinks: Boolean,
@ -52,7 +58,7 @@ data class Stream(
interface MediaRepository { interface MediaRepository {
fun getRepoInfo() : RepoMetaInfo fun getRepoInfo(): RepoMetaInfo
suspend fun getMetaInfo(item: String): MediaMetadata suspend fun getMetaInfo(item: String): MediaMetadata

View File

@ -37,7 +37,7 @@ enum class PlayMode {
} }
enum class RepeatMode { enum class RepeatMode {
DONT_REPEAT, DO_NOT_REPEAT,
REPEAT_ALL, REPEAT_ALL,
REPEAT_ONE REPEAT_ONE
} }

View File

@ -100,14 +100,14 @@ class NewPlayerImpl(
override var repeatMode: RepeatMode override var repeatMode: RepeatMode
get() = when (exoPlayer.value?.repeatMode) { get() = when (exoPlayer.value?.repeatMode) {
Player.REPEAT_MODE_OFF -> RepeatMode.DONT_REPEAT Player.REPEAT_MODE_OFF -> RepeatMode.DO_NOT_REPEAT
Player.REPEAT_MODE_ALL -> RepeatMode.REPEAT_ALL Player.REPEAT_MODE_ALL -> RepeatMode.REPEAT_ALL
Player.REPEAT_MODE_ONE -> RepeatMode.REPEAT_ONE Player.REPEAT_MODE_ONE -> RepeatMode.REPEAT_ONE
else -> throw NewPlayerException("Unknown Repeatmode option returned by ExoPlayer: ${exoPlayer.value?.repeatMode}") else -> throw NewPlayerException("Unknown Repeatmode option returned by ExoPlayer: ${exoPlayer.value?.repeatMode}")
} }
set(value) { set(value) {
when (value) { when (value) {
RepeatMode.DONT_REPEAT -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_OFF RepeatMode.DO_NOT_REPEAT -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_OFF
RepeatMode.REPEAT_ALL -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ALL RepeatMode.REPEAT_ALL -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ALL
RepeatMode.REPEAT_ONE -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ONE RepeatMode.REPEAT_ONE -> exoPlayer.value?.repeatMode = Player.REPEAT_MODE_ONE
} }

View File

@ -96,7 +96,7 @@ data class VideoPlayerUIState(
playList = emptyList(), playList = emptyList(),
chapters = emptyList(), chapters = emptyList(),
shuffleEnabled = false, shuffleEnabled = false,
repeatMode = RepeatMode.DONT_REPEAT, repeatMode = RepeatMode.DO_NOT_REPEAT,
playListDurationInS = 0, playListDurationInS = 0,
currentlyPlaying = null, currentlyPlaying = null,
currentPlaylistItemIndex = 0 currentPlaylistItemIndex = 0

View File

@ -415,6 +415,10 @@ class VideoPlayerViewModelImpl @Inject constructor(
} }
override fun finishFastSeek() { override fun finishFastSeek() {
if (mutableUiState.value.uiMode.controllerUiVisible) {
resetHideUiDelayedJob()
}
val fastSeekAmount = mutableUiState.value.fastSeekSeconds val fastSeekAmount = mutableUiState.value.fastSeekSeconds
if (fastSeekAmount != 0) { if (fastSeekAmount != 0) {
Log.d(TAG, "$fastSeekAmount") Log.d(TAG, "$fastSeekAmount")
@ -513,9 +517,9 @@ class VideoPlayerViewModelImpl @Inject constructor(
override fun cycleRepeatMode() { override fun cycleRepeatMode() {
newPlayer?.let { newPlayer?.let {
it.repeatMode = when (it.repeatMode) { it.repeatMode = when (it.repeatMode) {
RepeatMode.DONT_REPEAT -> RepeatMode.REPEAT_ALL RepeatMode.DO_NOT_REPEAT -> RepeatMode.REPEAT_ALL
RepeatMode.REPEAT_ALL -> RepeatMode.REPEAT_ONE RepeatMode.REPEAT_ALL -> RepeatMode.REPEAT_ONE
RepeatMode.REPEAT_ONE -> RepeatMode.DONT_REPEAT RepeatMode.REPEAT_ONE -> RepeatMode.DO_NOT_REPEAT
} }
} }
} }

View File

@ -81,7 +81,7 @@ fun StreamSelectTopBar(
onClick = viewModel::cycleRepeatMode onClick = viewModel::cycleRepeatMode
) { ) {
when (uiState.repeatMode) { when (uiState.repeatMode) {
RepeatMode.DONT_REPEAT -> Icon( RepeatMode.DO_NOT_REPEAT -> Icon(
imageVector = Icons.Filled.Repeat, imageVector = Icons.Filled.Repeat,
contentDescription = stringResource(R.string.repeat_mode_no_repeat) contentDescription = stringResource(R.string.repeat_mode_no_repeat)
) )

View File

@ -0,0 +1,75 @@
package net.newpipe.newplayer.utils
import androidx.annotation.OptIn
import androidx.media3.common.MediaItem
import androidx.media3.common.Tracks
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.HttpDataSource
import androidx.media3.exoplayer.dash.DashMediaSource
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.MergingMediaSource
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import kotlinx.coroutines.flow.MutableSharedFlow
import net.newpipe.newplayer.MediaRepository
import net.newpipe.newplayer.StreamType
import net.newpipe.newplayer.StreamVariant
import kotlin.random.Random
class MediaSourceBuilder(
private val repository: MediaRepository,
private val uniqueIdToIdLookup: HashMap<Long, String>,
private val mutableErrorFlow: MutableSharedFlow<Exception>,
private val httpDataSourceFactory: HttpDataSource.Factory
) {
suspend fun buildMediaSource(item: String) {
val availableStreamVariants = repository.getAvailableStreamVariants(item)
val tracks: Tracks? = null
MergingMediaSource
}
@OptIn(UnstableApi::class)
private suspend
fun toMediaItem(item: String, streamVariant: StreamVariant): MediaItem {
val dataStream = repository.getStream(item, streamVariant)
val uniqueId = Random.nextLong()
uniqueIdToIdLookup[uniqueId] = item
val mediaItemBuilder = MediaItem.Builder()
.setMediaId(uniqueId.toString())
.setUri(dataStream.streamUri)
if (dataStream.mimeType != null) {
mediaItemBuilder.setMimeType(dataStream.mimeType)
}
return mediaItemBuilder.build()
}
@OptIn(UnstableApi::class)
private fun toMediaSource(mediaItem: MediaItem, streamVariant: StreamVariant) =
if (streamVariant.streamType == StreamType.DYNAMIC)
DashMediaSource.Factory(httpDataSourceFactory)
.createMediaSource(mediaItem)
else
ProgressiveMediaSource.Factory(httpDataSourceFactory)
.createMediaSource(mediaItem)
private suspend fun
addMetadata(mediaItem: MediaItem, item: String): MediaItem {
val mediaItemBuilder = mediaItem.buildUpon()
try {
val metadata = repository.getMetaInfo(item)
mediaItemBuilder.setMediaMetadata(metadata)
} catch (e: Exception) {
mutableErrorFlow.emit(e)
}
return mediaItemBuilder.build()
}
}

View File

@ -44,7 +44,7 @@
<integer name="portrait_length">23</integer> <integer name="portrait_length">23</integer>
<!-- "Intel Management Engine deep dive" a talk from 36c3 --> <!-- "Intel Management Engine deep dive" a talk from 36c3 -->
<string name ="ccc_imu_link" translatable="false">https://media.ccc.de/v/36c3-10694-intel_management_engine_deep_dive</string> <string name="ccc_imu_link" translatable="false">https://media.ccc.de/v/36c3-10694-intel_management_engine_deep_dive</string>
<string name="ccc_imu_1080_mp4" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_hd.mp4</string> <string name="ccc_imu_1080_mp4" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_hd.mp4</string>
<string name="ccc_imu_576_mp4" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-sd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_sd.mp4</string> <string name="ccc_imu_576_mp4" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/h264-sd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_sd.mp4</string>
<string name="ccc_imu_1080_webm" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/webm-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_webm-hd.webm</string> <string name="ccc_imu_1080_webm" translatable="false">https://ftp.fau.de/cdn.media.ccc.de/congress/2019/webm-hd/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive_webm-hd.webm</string>
@ -64,4 +64,17 @@
</integer-array> </integer-array>
<string name="ccc_imu_subtitles" translatable="false">https://cdn.media.ccc.de/congress/2019/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive.en.srt</string> <string name="ccc_imu_subtitles" translatable="false">https://cdn.media.ccc.de/congress/2019/36c3-10694-eng-deu-Intel_Management_Engine_deep_dive.en.srt</string>
<integer name="ccc_imu_length">3607</integer> <integer name="ccc_imu_length">3607</integer>
<!-- "Reverse Engineering the MOS 6502 CPU" a talk from 27c3 -->
<string name="yt_test_link" translatable="false">https://cloud.newpipe-ev.de/files/link/public/RyuyJKSUEzsHtwB</string>
<string name="yt_test_video_fullhd" translatable="false">https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/fullhd.mp4</string>
<string name="yt_test_video_hd" translatable="false">https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/hd.mp4</string>
<string name="yt_test_video_sd" translatable="false">https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/sd.mp4</string>
<string name="yt_test_audio_english" translatable="false">https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/english.m4a</string>
<string name="yt_test_audio_spanish" translatable="false">https://cloud.newpipe-ev.de/remote.php/dav/public-files/RyuyJKSUEzsHtwB/spanish.m4a</string>
<string name="yt_test_title" translatable="false">Some YT Test video</string>
<string name="yt_test_channel" translatable="false">A Channel on YT</string>
<integer name="yt_test_length">254</integer>
</resources> </resources>