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);

View File

@ -363,12 +363,14 @@
</string-array>
<string-array name="revanced_spoof_streaming_data_type_entries">
<item>@string/revanced_spoof_streaming_data_type_entry_android_vr</item>
<item>@string/revanced_spoof_streaming_data_type_entry_android_vr_no_auth</item>
<item>@string/revanced_spoof_streaming_data_type_entry_android_unplugged</item>
<item>@string/revanced_spoof_streaming_data_type_entry_ios_unplugged</item>
<item>@string/revanced_spoof_streaming_data_type_entry_ios</item>
</string-array>
<string-array name="revanced_spoof_streaming_data_type_entry_values">
<item>ANDROID_VR</item>
<item>ANDROID_VR_NO_AUTH</item>
<item>ANDROID_UNPLUGGED</item>
<item>IOS_UNPLUGGED</item>
<item>IOS</item>

View File

@ -1980,6 +1980,8 @@ Tap the continue button and allow optimization changes."</string>
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">"Android TV
<small>(Login required)</small>"</string>
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
<string name="revanced_spoof_streaming_data_type_entry_android_vr_no_auth">"Android VR
<small>(No auth)</small>"</string>
<string name="revanced_spoof_streaming_data_type_entry_ios">"iOS
<small>(PoToken required)</small>"</string>
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">"iOS TV
@ -2001,6 +2003,7 @@ AVC has a maximum resolution of 1080p, Opus audio codec is not available, and vi
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Show in Stats for nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Client used to fetch streaming data is shown in Stats for nerds.</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Client used to fetch streaming data is hidden in Stats for nerds.</string>
<string name="revanced_spoof_streaming_data_language_title">VR default audio stream language</string>
<!-- PreferenceScreen: Miscellaneous, PreferenceCategory: Miscellaneous, PreferenceScreen: Spoof streaming data, PreferenceCategory: PoToken / VisitorData -->
<string name="revanced_preference_category_po_token_visitor_data">PoToken / VisitorData</string>

View File

@ -4,4 +4,5 @@
<string name="revanced_spoof_streaming_data_side_effects_android_creator">@string/revanced_spoof_streaming_data_side_effects_android</string>
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">@string/revanced_spoof_streaming_data_side_effects_android</string>
<string name="revanced_spoof_streaming_data_side_effects_android_vr">@string/revanced_spoof_streaming_data_side_effects_android</string>
<string name="revanced_spoof_streaming_data_side_effects_android_vr_no_auth">@string/revanced_spoof_streaming_data_side_effects_android</string>
</resources>

View File

@ -797,6 +797,7 @@
<ListPreference android:entries="@array/revanced_spoof_streaming_data_type_entries" android:title="@string/revanced_spoof_streaming_data_type_title" android:key="revanced_spoof_streaming_data_type" android:entryValues="@array/revanced_spoof_streaming_data_type_entry_values" android:dependency="revanced_spoof_streaming_data" />
<app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference android:title="@string/revanced_spoof_streaming_data_side_effects_title" />
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_ios_force_avc_title" android:key="revanced_spoof_streaming_data_ios_force_avc" android:summaryOn="@string/revanced_spoof_streaming_data_ios_force_avc_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_ios_force_avc_summary_off" android:dependency="revanced_spoof_streaming_data" />
<ListPreference android:entries="@array/revanced_language_entries" android:title="@string/revanced_spoof_streaming_data_language_title" android:key="revanced_spoof_streaming_data_language" android:entryValues="@array/revanced_language_entry_values" android:dependency="revanced_spoof_streaming_data" />
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_stats_for_nerds_title" android:key="revanced_spoof_streaming_data_stats_for_nerds" android:summaryOn="@string/revanced_spoof_streaming_data_stats_for_nerds_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_stats_for_nerds_summary_off" android:dependency="revanced_spoof_streaming_data" />
<PreferenceCategory android:title="@string/revanced_preference_category_po_token_visitor_data" android:layout="@layout/revanced_settings_preferences_category" />
<app.revanced.extension.shared.settings.preference.ResettableEditTextPreference android:title="@string/revanced_spoof_streaming_data_po_token_title" android:key="revanced_spoof_streaming_data_po_token" android:summary="@string/revanced_spoof_streaming_data_po_token_summary" android:inputType="text" android:dependency="revanced_spoof_streaming_data" />