feat(YouTube - Spoof streaming data): Add VR default audio stream language setting https://github.com/inotia00/ReVanced_Extended/issues/2670

This commit is contained in:
inotia00
2025-01-17 14:46:09 +09:00
parent b211df4288
commit e7f7d72e27
9 changed files with 66 additions and 14 deletions

View File

@ -316,6 +316,10 @@ object AppClient {
* Whether a poToken is required to get playback for more than 1 minute.
*/
val requirePoToken: Boolean = false,
/**
* Client name for innertube body.
*/
val clientName: String,
/**
* Friendly name displayed in stats for nerds.
*/
@ -330,8 +334,22 @@ object AppClient {
androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_VR,
clientVersion = CLIENT_VERSION_ANDROID_VR,
chipset = CHIPSET_ANDROID_VR,
clientName = "ANDROID_VR",
friendlyName = "Android VR"
),
ANDROID_VR_NO_AUTH(
id = 28,
deviceMake = DEVICE_MAKE_ANDROID_VR,
deviceModel = DEVICE_MODEL_ANDROID_VR,
osVersion = OS_VERSION_ANDROID_VR,
userAgent = USER_AGENT_ANDROID_VR,
androidSdkVersion = ANDROID_SDK_VERSION_ANDROID_VR,
clientVersion = CLIENT_VERSION_ANDROID_VR,
chipset = CHIPSET_ANDROID_VR,
supportsCookies = false,
clientName = "ANDROID_VR",
friendlyName = "Android VR No auth"
),
ANDROID_UNPLUGGED(
id = 29,
deviceMake = DEVICE_MAKE_ANDROID_UNPLUGGED,
@ -343,6 +361,7 @@ object AppClient {
gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_UNPLUGGED,
chipset = CHIPSET_ANDROID_UNPLUGGED,
requireAuth = true,
clientName = "ANDROID_UNPLUGGED",
friendlyName = "Android TV"
),
ANDROID_CREATOR(
@ -356,6 +375,7 @@ object AppClient {
gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_CREATOR,
chipset = CHIPSET_ANDROID_CREATOR,
requireAuth = true,
clientName = "ANDROID_CREATOR",
friendlyName = "Android Studio"
),
IOS_UNPLUGGED(
@ -367,6 +387,7 @@ object AppClient {
userAgent = USER_AGENT_IOS_UNPLUGGED,
clientVersion = CLIENT_VERSION_IOS_UNPLUGGED,
requireAuth = true,
clientName = "IOS_UNPLUGGED",
friendlyName = if (forceAVC())
"iOS TV Force AVC"
else
@ -382,6 +403,7 @@ object AppClient {
clientVersion = CLIENT_VERSION_IOS,
supportsCookies = false,
requirePoToken = true,
clientName = "IOS",
friendlyName = if (forceAVC())
"iOS Force AVC"
else
@ -398,11 +420,10 @@ object AppClient {
gmscoreVersionCode = GMS_CORE_VERSION_CODE_ANDROID_MUSIC,
chipset = CHIPSET_ANDROID_MUSIC,
requireAuth = true,
clientName = "ANDROID_MUSIC",
friendlyName = "Android Music"
);
val clientName: String = name
companion object {
val CLIENT_ORDER_TO_USE_YOUTUBE: Array<ClientType> = arrayOf(
ANDROID_VR,
@ -410,6 +431,7 @@ object AppClient {
IOS_UNPLUGGED,
ANDROID_CREATOR,
IOS,
ANDROID_VR_NO_AUTH,
)
internal val CLIENT_ORDER_TO_USE_YOUTUBE_MUSIC: Array<ClientType> = arrayOf(

View File

@ -13,8 +13,10 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
import app.revanced.extension.shared.patches.spoof.requests.StreamingDataRequest;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.Utils;
@ -341,4 +343,12 @@ public class SpoofStreamingDataPatch {
return videoFormat;
}
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_STREAMING_DATA.get() &&
BaseSettings.SPOOF_STREAMING_DATA_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
}
}
}

View File

@ -5,6 +5,7 @@ import app.revanced.extension.shared.patches.client.WebClient
import app.revanced.extension.shared.requests.Requester
import app.revanced.extension.shared.requests.Route
import app.revanced.extension.shared.requests.Route.CompiledRoute
import app.revanced.extension.shared.settings.BaseSettings
import app.revanced.extension.shared.utils.Logger
import app.revanced.extension.shared.utils.Utils
import org.apache.commons.lang3.StringUtils
@ -77,7 +78,7 @@ object PlayerRoutes {
client.put("clientVersion", clientType.clientVersion)
client.put("osName", clientType.osName)
client.put("osVersion", clientType.osVersion)
if (clientType.osName != "iOS") {
if (clientType.osName == "Android") {
client.put("androidSdkVersion", clientType.androidSdkVersion)
if (clientType.gmscoreVersionCode != null) {
client.put("gmscoreVersionCode", clientType.gmscoreVersionCode)
@ -86,12 +87,18 @@ object PlayerRoutes {
client.put("chipset", clientType.chipset)
}
}
if (setLocale) {
client.put("hl", LOCALE_LANGUAGE)
client.put("gl", LOCALE_COUNTRY)
client.put("timeZone", TIME_ZONE_ID)
client.put("utcOffsetMinutes", "$UTC_OFFSET_MINUTES")
}
client.put(
"hl",
if (setLocale) {
BaseSettings.SPOOF_STREAMING_DATA_LANGUAGE.get().language
} else {
LOCALE_LANGUAGE
}
)
client.put("gl", LOCALE_COUNTRY)
client.put("timeZone", TIME_ZONE_ID)
client.put("utcOffsetMinutes", "$UTC_OFFSET_MINUTES")
val context = JSONObject()
context.put("client", client)

View File

@ -93,9 +93,14 @@ class StreamingDataRequest private constructor(
"X-GOOG-API-FORMAT-VERSION",
VISITOR_ID_HEADER
)
private val SPOOF_STREAMING_DATA_TYPE: AppClient.ClientType =
BaseSettings.SPOOF_STREAMING_DATA_TYPE.get()
private val CLIENT_ORDER_TO_USE: Array<AppClient.ClientType> =
availableClientTypes(BaseSettings.SPOOF_STREAMING_DATA_TYPE.get())
availableClientTypes(SPOOF_STREAMING_DATA_TYPE)
private val DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH: Boolean =
SPOOF_STREAMING_DATA_TYPE == AppClient.ClientType.ANDROID_VR_NO_AUTH
private var lastSpoofedClientType: AppClient.ClientType? = null
@ -177,8 +182,6 @@ class StreamingDataRequest private constructor(
connection.connectTimeout = HTTP_TIMEOUT_MILLISECONDS
connection.readTimeout = HTTP_TIMEOUT_MILLISECONDS
val setLocale =
!clientType.supportsCookies || playerHeaders[AUTHORIZATION_HEADER] == null
val usePoToken =
clientType.requirePoToken && !StringUtils.isAnyEmpty(botGuardPoToken, visitorId)
@ -209,7 +212,7 @@ class StreamingDataRequest private constructor(
videoId = videoId,
botGuardPoToken = botGuardPoToken,
visitorId = visitorId,
setLocale = setLocale
setLocale = DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH,
)
Logger.printDebug { "Set poToken (botGuardPoToken):\n$botGuardPoToken" }
} else {
@ -217,9 +220,10 @@ class StreamingDataRequest private constructor(
createApplicationRequestBody(
clientType = clientType,
videoId = videoId,
setLocale = setLocale
setLocale = DEFAULT_CLIENT_IS_ANDROID_VR_NO_AUTH,
)
}
connection.setFixedLengthStreamingMode(requestBody.size)
connection.outputStream.write(requestBody)

View File

@ -6,6 +6,7 @@ import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAd
import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat;
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
import app.revanced.extension.shared.patches.spoof.SpoofStreamingDataPatch.AudioStreamLanguageOverrideAvailability;
/**
* Settings shared across multiple apps.
@ -39,6 +40,7 @@ public class BaseSettings {
public static final StringSetting RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY = new StringSetting("revanced_return_youtube_username_youtube_data_api_v3_developer_key", "", true, false);
public static final BooleanSetting SPOOF_STREAMING_DATA = new BooleanSetting("revanced_spoof_streaming_data", TRUE, true, "revanced_spoof_streaming_data_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_STREAMING_DATA_LANGUAGE = new EnumSetting<>("revanced_spoof_streaming_data_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
public static final BooleanSetting SPOOF_STREAMING_DATA_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_streaming_data_ios_force_avc", FALSE, true,
"revanced_spoof_streaming_data_ios_force_avc_user_dialog_message");
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE);