Skip to content

Commit

Permalink
Support 1080p quality video
Browse files Browse the repository at this point in the history
  • Loading branch information
maxrave-dev committed Jun 23, 2024
1 parent fec5ade commit 9c7c272
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 48 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/com/maxrave/simpmusic/common/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ object QUALITY {
}

object VIDEO_QUALITY {
val items: Array<CharSequence> = arrayOf("720p", "360p")
val itags: Array<Int> = arrayOf(22, 18)
val items: Array<CharSequence> = arrayOf("1080p", "720p", "360p")
val itags: Array<Int> = arrayOf(137, 136, 134)
}

object LYRICS_PROVIDER {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,9 @@ interface DatabaseDao {
@Query("SELECT * FROM new_format WHERE videoId = :videoId")
suspend fun getNewFormat(videoId: String): NewFormatEntity?

@Query("SELECT * FROM new_format WHERE videoId = :videoId")
fun getNewFormatAsFlow(videoId: String): Flow<NewFormatEntity?>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertSongInfo(songInfo: SongInfoEntity)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ class LocalDataSource

suspend fun getNewFormat(videoId: String) = databaseDao.getNewFormat(videoId)

suspend fun getNewFormatAsFlow(videoId: String) = databaseDao.getNewFormatAsFlow(videoId)

suspend fun insertSongInfo(songInfo: SongInfoEntity) = databaseDao.insertSongInfo(songInfo)

suspend fun getSongInfo(videoId: String) = databaseDao.getSongInfo(videoId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.maxrave.simpmusic.data.repository

import android.content.Context
import android.util.Log
import androidx.media3.common.util.UnstableApi
import com.maxrave.kotlinytmusicscraper.YouTube
import com.maxrave.kotlinytmusicscraper.models.AccountInfo
import com.maxrave.kotlinytmusicscraper.models.MediaType
Expand All @@ -21,6 +22,7 @@ import com.maxrave.kotlinytmusicscraper.pages.BrowseResult
import com.maxrave.kotlinytmusicscraper.pages.PlaylistPage
import com.maxrave.kotlinytmusicscraper.pages.SearchPage
import com.maxrave.simpmusic.R
import com.maxrave.simpmusic.common.QUALITY
import com.maxrave.simpmusic.common.VIDEO_QUALITY
import com.maxrave.simpmusic.data.dataStore.DataStoreManager
import com.maxrave.simpmusic.data.db.LocalDataSource
Expand Down Expand Up @@ -84,6 +86,7 @@ import com.maxrave.simpmusic.extension.bestMatchingIndex
import com.maxrave.simpmusic.extension.toListTrack
import com.maxrave.simpmusic.extension.toLyrics
import com.maxrave.simpmusic.extension.toTrack
import com.maxrave.simpmusic.service.test.source.MergingMediaSourceFactory
import com.maxrave.simpmusic.utils.Resource
import com.maxrave.simpmusic.viewModel.FilterState
import dagger.hilt.android.qualifiers.ApplicationContext
Expand Down Expand Up @@ -420,6 +423,8 @@ class MainRepository
suspend fun getNewFormat(videoId: String): Flow<NewFormatEntity?> =
flow { emit(localDataSource.getNewFormat(videoId)) }.flowOn(Dispatchers.Main)

suspend fun getFormatFlow(videoId: String) = localDataSource.getNewFormatAsFlow(videoId)

suspend fun insertSongInfo(songInfo: SongInfoEntity) =
withContext(Dispatchers.IO) {
localDataSource.insertSongInfo(songInfo)
Expand Down Expand Up @@ -2146,10 +2151,14 @@ class MainRepository
}
}.flowOn(Dispatchers.IO)

@UnstableApi
suspend fun getSongInfo(videoId: String): Flow<SongInfoEntity?> =
flow {
runCatching {
YouTube.getSongInfo(videoId).onSuccess { songInfo ->
val id = if (videoId.contains(MergingMediaSourceFactory.isVideo))
videoId.removePrefix(MergingMediaSourceFactory.isVideo)
else videoId
YouTube.getSongInfo(id).onSuccess { songInfo ->
val song =
SongInfoEntity(
videoId = songInfo.videoId,
Expand All @@ -2174,19 +2183,20 @@ class MainRepository
}
}.flowOn(Dispatchers.IO)

@UnstableApi
suspend fun getStream(
videoId: String,
itag: Int,
isVideo: Boolean,
): Flow<String?> =
flow {
//134, 136, 137
YouTube.player(videoId).onSuccess { data ->
val acceptToPlayVideo =
runBlocking { dataStoreManager.watchVideoInsteadOfPlayingAudio.first() == DataStoreManager.TRUE }
val itag = QUALITY.itags.getOrNull(QUALITY.items.indexOf(dataStoreManager.quality.first()))
val videoItag =
VIDEO_QUALITY.itags.getOrNull(
VIDEO_QUALITY.items.indexOf(dataStoreManager.videoQuality.first()),
)
?: 22
?: 134
val response = data.second
if (data.third == MediaType.Song) {
Log.w(
Expand All @@ -2196,18 +2206,14 @@ class MainRepository
} else {
Log.w("Stream", "response: is VIDEO")
}
Log.w("Stream: ", data.toString())
Log.w("Stream", response.streamingData?.formats?.map { it.itag }.toString() + " " +
response.streamingData?.adaptiveFormats?.map { it.itag }.toString())

Log.w("Stream", "Get stream for video $isVideo")
var format =
if (acceptToPlayVideo) {
if (data.third == MediaType.Song) {
if (response.streamingData?.adaptiveFormats?.find { it.itag == 141 } != null) {
response.streamingData?.adaptiveFormats?.find { it.itag == 141 }
} else {
response.streamingData?.adaptiveFormats?.find { it.itag == itag }
}
} else {
response.streamingData?.formats?.find { it.itag == videoItag }
}
if (isVideo) {
response.streamingData?.formats?.find { it.itag == videoItag }
?: response.streamingData?.adaptiveFormats?.find { it.itag == videoItag }
} else {
if (response.streamingData?.adaptiveFormats?.find { it.itag == 141 } != null) {
response.streamingData?.adaptiveFormats?.find { it.itag == 141 }
Expand All @@ -2222,8 +2228,8 @@ class MainRepository
runBlocking {
insertNewFormat(
NewFormatEntity(
videoId = videoId,
itag = format?.itag ?: itag,
videoId = if(VIDEO_QUALITY.itags.contains(format?.itag)) "${MergingMediaSourceFactory.isVideo}$videoId" else videoId,
itag = format?.itag ?: itag ?: 141,
mimeType =
Regex("""([^;]+);\s*codecs=["']([^"']+)["']""").find(
format?.mimeType ?: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@ import androidx.media3.session.SessionToken
import com.google.common.util.concurrent.MoreExecutors
import com.maxrave.simpmusic.R
import com.maxrave.simpmusic.common.MEDIA_NOTIFICATION
import com.maxrave.simpmusic.common.QUALITY
import com.maxrave.simpmusic.data.dataStore.DataStoreManager
import com.maxrave.simpmusic.data.repository.MainRepository
import com.maxrave.simpmusic.di.DownloadCache
import com.maxrave.simpmusic.di.PlayerCache
import com.maxrave.simpmusic.service.test.CoilBitmapLoader
import com.maxrave.simpmusic.service.test.source.MergingMediaSourceFactory
import com.maxrave.simpmusic.ui.MainActivity
import com.maxrave.simpmusic.ui.widget.BasicWidget
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import javax.inject.Inject

Expand Down Expand Up @@ -100,7 +99,7 @@ class SimpleMediaService : MediaLibraryService() {
.setHandleAudioBecomingNoisy(true)
.setSeekForwardIncrementMs(5000)
.setSeekBackIncrementMs(5000)
.setMediaSourceFactory(provideMediaSourceFactory())
.setMediaSourceFactory(provideMergingMediaSource())
.setRenderersFactory(provideRendererFactory(this))
.build()

Expand Down Expand Up @@ -230,11 +229,12 @@ class SimpleMediaService : MediaLibraryService() {
cacheDataSourceFactory: CacheDataSource.Factory,
@DownloadCache downloadCache: SimpleCache,
@PlayerCache playerCache: SimpleCache,
mainRepository: MainRepository,
dataStoreManager: DataStoreManager
mainRepository: MainRepository
): DataSource.Factory {
return ResolvingDataSource.Factory(cacheDataSourceFactory) { dataSpec ->
val mediaId = dataSpec.key ?: error("No media id")
var mediaId = dataSpec.key ?: error("No media id")
Log.w("Stream", mediaId)
Log.w("Stream", mediaId.startsWith(MergingMediaSourceFactory.isVideo).toString())
val CHUNK_LENGTH = 512 * 1024L
if (downloadCache.isCached(
mediaId,
Expand All @@ -246,14 +246,23 @@ class SimpleMediaService : MediaLibraryService() {
}
var dataSpecReturn: DataSpec = dataSpec
runBlocking(Dispatchers.IO) {
val itag = dataStoreManager.quality.first()

mainRepository.getStream(
mediaId,
if (itag == QUALITY.items[0].toString()) QUALITY.itags[0] else QUALITY.itags[1]
).cancellable().collect {
if (it != null) {
dataSpecReturn = dataSpec.withUri(it.toUri())
if (mediaId.contains(MergingMediaSourceFactory.isVideo)) {
val id = mediaId.removePrefix(MergingMediaSourceFactory.isVideo)
mainRepository.getStream(
id, true
).cancellable().collect {
if (it != null) {
dataSpecReturn = dataSpec.withUri(it.toUri())
}
}
}
else {
mainRepository.getStream(
mediaId, isVideo = false
).cancellable().collect {
if (it != null) {
dataSpecReturn = dataSpec.withUri(it.toUri())
}
}
}
}
Expand All @@ -277,12 +286,16 @@ class SimpleMediaService : MediaLibraryService() {
provideCacheDataSource(downloadCache, playerCache),
downloadCache,
playerCache,
mainRepository,
dataStoreManager
mainRepository
),
provideExtractorFactory()
)

private fun provideMergingMediaSource(): MergingMediaSourceFactory = MergingMediaSourceFactory(
provideMediaSourceFactory(),
dataStoreManager
)

@UnstableApi
fun provideRendererFactory(context: Context): DefaultRenderersFactory =
object : DefaultRenderersFactory(context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,8 @@ class SimpleMediaServiceHandler(
thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544")
}
val artistName: String = track.artists.toListName().connectArtists()
val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width
&& track.thumbnails?.last()?.height != null)
if (track.artists.isNullOrEmpty()) {
mainRepository.getSongInfo(track.videoId).singleOrNull()
.let { songInfo ->
Expand All @@ -862,6 +864,7 @@ class SimpleMediaServiceHandler(
.setArtist(songInfo.author)
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build(),
Expand All @@ -878,6 +881,7 @@ class SimpleMediaServiceHandler(
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setArtist("Various Artists")
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build()
Expand All @@ -900,6 +904,7 @@ class SimpleMediaServiceHandler(
.setArtist(artistName)
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build(),
Expand Down Expand Up @@ -929,6 +934,8 @@ class SimpleMediaServiceHandler(
if (thumbUrl.contains("w120")) {
thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544")
}
val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width &&
track.thumbnails?.last()?.height != null)
if (downloaded == 1) {
if (track.artists.isNullOrEmpty()) {
mainRepository.getSongInfo(track.videoId).singleOrNull()
Expand All @@ -945,6 +952,7 @@ class SimpleMediaServiceHandler(
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setArtist(songInfo.author)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build()
Expand Down Expand Up @@ -972,6 +980,7 @@ class SimpleMediaServiceHandler(
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setArtist("Various Artists")
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build()
Expand All @@ -995,6 +1004,7 @@ class SimpleMediaServiceHandler(
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setArtist(track.artists.toListName().connectArtists())
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build()
Expand Down Expand Up @@ -1029,6 +1039,7 @@ class SimpleMediaServiceHandler(
.setTitle(track.title)
.setArtist(songInfo.author)
.setArtworkUri(thumbUrl.toUri())
.setDescription(if (isSong) "Song" else "Video")
.setAlbumTitle(track.album?.name)
.build(),
)
Expand All @@ -1045,6 +1056,7 @@ class SimpleMediaServiceHandler(
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setDescription(if (isSong) "Song" else "Video")
.setArtist("Various Artists")
.build(),
)
Expand All @@ -1068,6 +1080,7 @@ class SimpleMediaServiceHandler(
.setArtist(artistName)
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build(),
Expand Down Expand Up @@ -1136,6 +1149,8 @@ class SimpleMediaServiceHandler(
thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544")
}
val artistName: String = track.artists.toListName().connectArtists()
val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width &&
track.thumbnails?.last()?.height != null)
if ((currentIndex() + 1 in 0..catalogMetadata.size)) {
if (track.artists.isNullOrEmpty()) {
mainRepository.getSongInfo(track.videoId).cancellable().first().let { songInfo ->
Expand All @@ -1162,6 +1177,7 @@ class SimpleMediaServiceHandler(
.setArtist(songInfo.author)
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build(),
Expand All @@ -1179,6 +1195,7 @@ class SimpleMediaServiceHandler(
.setAlbumTitle(track.album?.name)
.setTitle(track.title)
.setArtist("Various Artists")
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build()
Expand All @@ -1202,6 +1219,7 @@ class SimpleMediaServiceHandler(
.setArtist(artistName)
.setArtworkUri(thumbUrl.toUri())
.setAlbumTitle(track.album?.name)
.setDescription(if (isSong) "Song" else "Video")
.build(),
)
.build(),
Expand Down
Loading

0 comments on commit 9c7c272

Please sign in to comment.