Skip to content

Commit

Permalink
WIP: innertube: register playback stuff
Browse files Browse the repository at this point in the history
* Adhere to pause listen history for remote content
  • Loading branch information
mikooomich committed Jan 10, 2025
1 parent 3d94855 commit b2e3444
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class DownloadUtil @Inject constructor(
playedFormat = playedFormat,
audioQuality = audioQuality,
connectivityManager = connectivityManager,
registerPlayback = false,
)
}.getOrThrow()
val format = playbackData.format
Expand Down
25 changes: 15 additions & 10 deletions app/src/main/java/com/dd3boh/outertune/playback/MusicService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -452,26 +452,19 @@ class MusicService : MediaLibraryService(),

if (playbackUrl == null) {
playbackUrl = if (playbackData?.playbackTracking?.videostatsPlaybackUrl?.baseUrl == null)
YTPlayerUtils.playerResponseForMetadata(mediaId, registerPlayback = false).getOrNull()?.playbackTracking
YTPlayerUtils.playerResponseForMetadata(mediaId).getOrNull()?.playbackTracking
?.videostatsPlaybackUrl?.baseUrl!!
else
playbackData.playbackTracking?.videostatsPlaybackUrl?.baseUrl
}

playbackUrl?.let {
try { YouTube.registerPlayback(queuePlaylistId, playbackUrl) }
catch (exception: UnknownHostException) {
reportException(exception)
}
}

val song = database.song(mediaId).first()
val mediaMetadata = withContext(Dispatchers.Main) {
player.findNextMediaItemById(mediaId)?.metadata
} ?: return
val duration = song?.song?.duration?.takeIf { it != -1 }
?: mediaMetadata.duration.takeIf { it != -1 }
?: (playbackData?.videoDetails ?: YTPlayerUtils.playerResponseForMetadata(mediaId, registerPlayback = false).getOrNull()?.videoDetails)?.lengthSeconds?.toInt()
?: (playbackData?.videoDetails ?: YTPlayerUtils.playerResponseForMetadata(mediaId).getOrNull()?.videoDetails)?.lengthSeconds?.toInt()
?: -1
database.query {
if (song == null) insert(mediaMetadata.copy(duration = duration))
Expand Down Expand Up @@ -696,7 +689,6 @@ class MusicService : MediaLibraryService(),
playedFormat = playedFormat,
audioQuality = audioQuality,
connectivityManager = connectivityManager,
registerPlayback = false,
)
}.getOrElse { throwable ->
when (throwable) {
Expand Down Expand Up @@ -822,6 +814,19 @@ class MusicService : MediaLibraryService(),
} catch (_: SQLException) {
}
}

// TODO: support playlist id
if (mediaItem.metadata?.isLocal != true) {
CoroutineScope(Dispatchers.IO).launch {
val playerResponse = YTPlayerUtils.playerResponseForMetadata(mediaItem.mediaId, null).getOrNull()
if (playerResponse?.playabilityStatus?.status == "OK") {
YouTube.registerPlayback(
playlistId = null,
playbackTracking = playerResponse.playbackTracking?.videostatsPlaybackUrl?.baseUrl!!
)
}
}
}
}
}

Expand Down
55 changes: 52 additions & 3 deletions app/src/main/java/com/dd3boh/outertune/utils/YTPlayerUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ object YTPlayerUtils {
playedFormat: FormatEntity?,
audioQuality: AudioQuality,
connectivityManager: ConnectivityManager,
registerPlayback: Boolean = false,
): Result<PlaybackData> = runCatching {
/**
* This is required for some clients to get working streams however
Expand Down Expand Up @@ -160,9 +159,8 @@ object YTPlayerUtils {
suspend fun playerResponseForMetadata(
videoId: String,
playlistId: String? = null,
registerPlayback: Boolean = false
): Result<PlayerResponse> =
YouTube.player(videoId, playlistId, client = MAIN_CLIENT, registerPlayback = registerPlayback)
YouTube.player(videoId, playlistId, client = MAIN_CLIENT)

private fun findFormat(
playerResponse: PlayerResponse,
Expand Down Expand Up @@ -228,4 +226,55 @@ object YTPlayerUtils {
}
.getOrNull()
}


/**
* OuterTune extras
*/



//
// /**
// * Add to remote playback history
// */
// fun registerPlayback(playlistId: String? = null, playbackTracking: String): Boolean {
// val cpn = (1..16).map {
// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[Random.Default.nextInt(
// 0,
// 64
// )]
// }.joinToString("")
//
// val playbackUrl = playbackTracking.replace(
// "https://s.youtube.com",
// "https://music.youtube.com",
// )
//

//// try {
// val baseUrl = playbackUrl.toHttpUrlOrNull() ?: throw IllegalArgumentException("Invalid URL: $playbackUrl")
// val httpBuilder = baseUrl.newBuilder()
// .addQueryParameter("ver", "2")
// .addQueryParameter("c", "WEB_REMIX")
// .addQueryParameter("cpn", cpn)
//
// if (playlistId != null) {
// httpBuilder.addQueryParameter("list", playlistId)
// httpBuilder.addQueryParameter("referrer", "https://music.youtube.com/playlist?list=$playlistId")
// }
//
// val requestBuilder = okhttp3.Request.Builder()
// .head()
// .url(httpBuilder.build())
//
// val response = httpClient.newCall(requestBuilder.build()).execute()
// return response.isSuccessful
//// } catch (e: Exception) {
//// reportException(e)
//// throw Exception("weh", e)
//// }
//
// return false
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ class InnerTube {
videoId: String,
playlistId: String?,
signatureTimestamp: Int?,
registerPlayback: Boolean = false,
) = httpClient.post("player") {
ytClient(client, setLogin = true)
setBody(
Expand Down
13 changes: 1 addition & 12 deletions innertube/src/main/java/com/zionhuang/innertube/YouTube.kt
Original file line number Diff line number Diff line change
Expand Up @@ -662,19 +662,8 @@ object YouTube {
playlistId: String? = null,
client: YouTubeClient,
signatureTimestamp: Int? = null,
registerPlayback: Boolean = true
): Result<PlayerResponse> = runCatching {
val playerResponse =
innerTube.player(client, videoId, playlistId, signatureTimestamp, registerPlayback).body<PlayerResponse>()

if (playerResponse.playabilityStatus.status == "OK") {
if (registerPlayback)
registerPlayback(playlistId, playerResponse.playbackTracking?.videostatsPlaybackUrl?.baseUrl!!)

return@runCatching playerResponse
}

playerResponse
innerTube.player(client, videoId, playlistId, signatureTimestamp).body<PlayerResponse>()
}

suspend fun registerPlayback(playlistId: String? = null, playbackTracking: String) {
Expand Down

0 comments on commit b2e3444

Please sign in to comment.