mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-26 12:11:02 +00:00
feat(YouTube - Spoof video streams): Add iPadOS client
This commit is contained in:
@@ -5,6 +5,7 @@ import static java.lang.Boolean.TRUE;
|
|||||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
|
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.spoof.ClientType;
|
import app.revanced.extension.shared.spoof.ClientType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,4 +33,11 @@ public class BaseSettings {
|
|||||||
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
|
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
|
||||||
// Client type must be last spoof setting due to cyclic references.
|
// Client type must be last spoof setting due to cyclic references.
|
||||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_1_61_48, true, parent(SPOOF_VIDEO_STREAMS));
|
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_1_61_48, true, parent(SPOOF_VIDEO_STREAMS));
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED) {
|
||||||
|
Logger.printInfo(() -> "Migrating from iOS Unplugged to iPadOS");
|
||||||
|
SPOOF_VIDEO_STREAMS_CLIENT_TYPE.save(ClientType.IPADOS);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantLocale")
|
||||||
public enum ClientType {
|
public enum ClientType {
|
||||||
/**
|
/**
|
||||||
* Video not playable: Kids / Paid / Movie / Private / Age-restricted.
|
* Video not playable: Kids / Paid / Movie / Private / Age-restricted.
|
||||||
@@ -87,6 +88,48 @@ public enum ClientType {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
"visionOS"
|
"visionOS"
|
||||||
|
),
|
||||||
|
/**
|
||||||
|
* The device machine id for the iPad 6th Gen (iPad7,6).
|
||||||
|
* AV1 hardware decoding is not supported.
|
||||||
|
* See [this GitHub Gist](https://gist.github.com/adamawolf/3048717) for more information.
|
||||||
|
*
|
||||||
|
* Based on Google's actions to date, PoToken may not be required on devices with very low specs.
|
||||||
|
* For example, suppose the User-Agent for a PlayStation 3 (with 256MB of RAM) is used.
|
||||||
|
* Accessing 'Web' (https://www.youtube.com) will redirect to 'TV' (https://www.youtube.com/tv).
|
||||||
|
* 'TV' target devices with very low specs, such as embedded devices, game consoles, and blu-ray players, so PoToken is not required.
|
||||||
|
*
|
||||||
|
* For this reason, the device machine id for the iPad 6th Gen (with 2GB of RAM),
|
||||||
|
* the lowest spec device capable of running iPadOS 17, was used.
|
||||||
|
*/
|
||||||
|
IPADOS(5,
|
||||||
|
"IOS",
|
||||||
|
"Apple",
|
||||||
|
"iPad7,6",
|
||||||
|
"iPadOS",
|
||||||
|
"17.7.10.21H450",
|
||||||
|
"19.22.3",
|
||||||
|
"com.google.ios.youtube/19.22.3 (iPad7,6; U; CPU iPadOS 17_7_10 like Mac OS X; " + Locale.getDefault() + ")",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
"iPadOS"
|
||||||
|
),
|
||||||
|
/**
|
||||||
|
* Obsolete and broken client. Here only to migrate data.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
IOS_UNPLUGGED(
|
||||||
|
33,
|
||||||
|
"IOS_UNPLUGGED",
|
||||||
|
"Apple",
|
||||||
|
"iPhone16,2",
|
||||||
|
"iOS",
|
||||||
|
"18.2.22C152",
|
||||||
|
"8.49",
|
||||||
|
"dummy user-agent",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
"iOS TV"
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,7 +216,6 @@ public enum ClientType {
|
|||||||
/**
|
/**
|
||||||
* Android constructor.
|
* Android constructor.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("ConstantLocale")
|
|
||||||
ClientType(int id,
|
ClientType(int id,
|
||||||
String clientName,
|
String clientName,
|
||||||
@NonNull String packageName,
|
@NonNull String packageName,
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ public class ForceOriginalAudioPatch {
|
|||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void setPreferredLanguage() {
|
public static void setPreferredLanguage() {
|
||||||
if (Settings.FORCE_ORIGINAL_AUDIO.get()) {
|
if (Settings.FORCE_ORIGINAL_AUDIO.get()
|
||||||
// None of the current spoof clients support audio track menu,
|
&& SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
|
||||||
// And all are un-authenticated and can request any language code
|
// If client spoofing does not use authentication and lacks multi-audio streams,
|
||||||
// (authenticated requests ignore the language code and always use the account language).
|
// then can use any language code for the request and if that requested language is
|
||||||
// To still support force original audio, if it's enabled then pick a language
|
// not available YT uses the original audio language. Authenticated requests ignore
|
||||||
// that is not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
|
// the language code and always use the account language. Use a language that is
|
||||||
|
// not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
|
||||||
// but the language is also supported natively by the Meta Quest device that
|
// but the language is also supported natively by the Meta Quest device that
|
||||||
// Android VR is spoofing.
|
// Android VR is spoofing.
|
||||||
AppLanguage override = AppLanguage.SV;
|
AppLanguage override = AppLanguage.SV;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package app.revanced.extension.youtube.patches.spoof;
|
|||||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_CREATOR;
|
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_CREATOR;
|
||||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
|
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
|
||||||
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
|
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
|
||||||
|
import static app.revanced.extension.shared.spoof.ClientType.IPADOS;
|
||||||
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
|
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -22,6 +23,7 @@ public class SpoofVideoStreamsPatch {
|
|||||||
ANDROID_VR_1_61_48,
|
ANDROID_VR_1_61_48,
|
||||||
ANDROID_CREATOR,
|
ANDROID_CREATOR,
|
||||||
VISIONOS,
|
VISIONOS,
|
||||||
|
IPADOS,
|
||||||
// VR 1.43 must be last as spoof streaming data handles it slightly differently.
|
// VR 1.43 must be last as spoof streaming data handles it slightly differently.
|
||||||
ANDROID_VR_1_43_32
|
ANDROID_VR_1_43_32
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -78,18 +78,25 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
|||||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||||
|
|
||||||
String title = str("revanced_spoof_video_streams_about_title");
|
setTitle(str("revanced_spoof_video_streams_about_title"));
|
||||||
// Currently only Android VR and VisionOS are supported, and both have the same base side effects.
|
|
||||||
String summary = str("revanced_spoof_video_streams_about_android_summary");
|
|
||||||
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
|
||||||
|
|
||||||
if (clientType == ClientType.VISIONOS) {
|
String summary = str(clientType == ClientType.IPADOS
|
||||||
|
? "revanced_spoof_video_streams_about_ipados_summary"
|
||||||
|
// visionOS has same base side effects as Android VR.
|
||||||
|
: "revanced_spoof_video_streams_about_android_summary");
|
||||||
|
|
||||||
|
if (clientType == ClientType.IPADOS) {
|
||||||
|
summary = str("revanced_spoof_video_streams_about_no_av1")
|
||||||
|
+ '\n' + summary;
|
||||||
|
} else if (clientType == ClientType.VISIONOS) {
|
||||||
summary = str("revanced_spoof_video_streams_about_experimental")
|
summary = str("revanced_spoof_video_streams_about_experimental")
|
||||||
+ '\n' + summary
|
+ '\n' + summary
|
||||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
|
||||||
|
+ '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||||
|
} else {
|
||||||
|
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle(title);
|
|
||||||
setSummary(summary);
|
setSummary(summary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,10 +125,12 @@
|
|||||||
<string-array name="revanced_spoof_video_streams_client_type_entries">
|
<string-array name="revanced_spoof_video_streams_client_type_entries">
|
||||||
<item>Android VR</item>
|
<item>Android VR</item>
|
||||||
<item>visionOS</item>
|
<item>visionOS</item>
|
||||||
|
<item>iPadOS</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_spoof_video_streams_client_type_entry_values">
|
<string-array name="revanced_spoof_video_streams_client_type_entry_values">
|
||||||
<item>ANDROID_VR_1_61_48</item>
|
<item>ANDROID_VR_1_61_48</item>
|
||||||
<item>VISIONOS</item>
|
<item>VISIONOS</item>
|
||||||
|
<item>IPADOS</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
</patch>
|
</patch>
|
||||||
</app>
|
</app>
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ If changing this setting does not take effect, try switching to Incognito mode."
|
|||||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio track menu is hidden
|
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio track menu is hidden
|
||||||
|
|
||||||
Audio track menu is not available when \'Spoof video streams\' is enabled"</string>
|
To show the Audio track menu, change \'Spoof video streams\' to iPadOS"</string>
|
||||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Hide Watch in VR</string>
|
<string name="revanced_hide_player_flyout_watch_in_vr_title">Hide Watch in VR</string>
|
||||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Watch in VR menu is hidden</string>
|
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Watch in VR menu is hidden</string>
|
||||||
@@ -1629,6 +1629,7 @@ Enabling this can unlock higher video qualities"</string>
|
|||||||
<string name="revanced_spoof_video_streams_about_android_title">Android spoofing side effects</string>
|
<string name="revanced_spoof_video_streams_about_android_title">Android spoofing side effects</string>
|
||||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Audio track menu is missing
|
<string name="revanced_spoof_video_streams_about_android_summary">"• Audio track menu is missing
|
||||||
• Stable volume is not available"</string>
|
• Stable volume is not available"</string>
|
||||||
|
<string name="revanced_spoof_video_streams_about_ipados_summary">• Video may stop at 1:00, or may not be available in some regions</string>
|
||||||
<string name="revanced_spoof_video_streams_about_experimental">• Experimental client and may stop working anytime</string>
|
<string name="revanced_spoof_video_streams_about_experimental">• Experimental client and may stop working anytime</string>
|
||||||
<string name="revanced_spoof_video_streams_about_no_av1">• No AV1 video codec</string>
|
<string name="revanced_spoof_video_streams_about_no_av1">• No AV1 video codec</string>
|
||||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Kids videos may not play when logged out or in incognito mode</string>
|
<string name="revanced_spoof_video_streams_about_kids_videos">• Kids videos may not play when logged out or in incognito mode</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user