Compare commits

..

20 Commits

Author SHA1 Message Date
semantic-release-bot
1db131e90e chore: Release v5.37.1-dev.3 [skip ci]
## [5.37.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.2...v5.37.1-dev.3) (2025-09-15)

### Bug Fixes

* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](abe3943f98))
2025-09-15 17:02:01 +00:00
LisoUseInAIKyrios
abe3943f98 fix(Spoof video streams): Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for Force original audio to work with any spoof client (#5861) 2025-09-15 20:58:56 +04:00
semantic-release-bot
cb6d802de3 chore: Release v5.37.1-dev.2 [skip ci]
## [5.37.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.1...v5.37.1-dev.2) (2025-09-15)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Support v397.1.0.52.81 ([#5855](https://github.com/ReVanced/revanced-patches/issues/5855)) ([f11d1ef](f11d1ef990))
2025-09-15 12:52:54 +00:00
brosssh
f11d1ef990 fix(Instagram - Hide navigation buttons): Support v397.1.0.52.81 (#5855) 2025-09-15 16:48:55 +04:00
semantic-release-bot
3d25da18bc chore: Release v5.37.1-dev.1 [skip ci]
## [5.37.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.0...v5.37.1-dev.1) (2025-09-15)

### Bug Fixes

* **YouTube Music - Spoof video streams:** Fix playback issues when using a cellular network ([fa04c8e](fa04c8eecf))
2025-09-15 12:47:02 +00:00
LisoUseInAIKyrios
fa04c8eecf fix(YouTube Music - Spoof video streams): Fix playback issues when using a cellular network
Code adapted from 5f35e51a27
2025-09-15 16:43:04 +04:00
semantic-release-bot
105f6e0e97 chore: Release v5.37.0 [skip ci]
# [5.37.0](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0) (2025-09-15)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](e6c79f1383))
* Resolve patching with dev branch ([09b941a](09b941abf0))
* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](dcd42454bd))
* **Viber - Hide ads:** Add constrain to known working version ([2db0948](2db0948bea))
* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](2a85a3b290))

### Features

* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](0abfab79d7))
2025-09-15 06:45:56 +00:00
LisoUseInAIKyrios
7d59efe05d chore: Merge branch dev to main (#5830) 2025-09-15 10:43:05 +04:00
github-actions[bot]
81ff5576b0 chore: Sync translations (#5854) 2025-09-15 10:41:42 +04:00
semantic-release-bot
9a5c102c0d chore: Release v5.37.0-dev.6 [skip ci]
# [5.37.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.5...v5.37.0-dev.6) (2025-09-15)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](e6c79f1383))
2025-09-15 06:40:30 +00:00
LisoUseInAIKyrios
e6c79f1383 fix(Instagram - Hide navigation buttons): Add constrain to known working version 2025-09-15 10:36:57 +04:00
semantic-release-bot
2a582eced8 chore: Release v5.37.0-dev.5 [skip ci]
# [5.37.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.4...v5.37.0-dev.5) (2025-09-15)

### Bug Fixes

* **Viber - Hide ads:** Add constrain to known working version ([2db0948](2db0948bea))
2025-09-15 06:29:31 +00:00
LisoUseInAIKyrios
2db0948bea fix(Viber - Hide ads): Add constrain to known working version 2025-09-15 10:26:30 +04:00
semantic-release-bot
a3ba92e742 chore: Release v5.37.0-dev.4 [skip ci]
# [5.37.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.3...v5.37.0-dev.4) (2025-09-14)

### Bug Fixes

* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](2a85a3b290))
2025-09-14 18:22:57 +00:00
LisoUseInAIKyrios
2a85a3b290 fix(YouTube Music - Spoof streaming data): Fix audio playback stuttering (#5839) 2025-09-14 22:19:13 +04:00
semantic-release-bot
eee72208dd chore: Release v5.37.0-dev.3 [skip ci]
# [5.37.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.2...v5.37.0-dev.3) (2025-09-14)

### Bug Fixes

* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](dcd42454bd))
2025-09-14 17:15:28 +00:00
LisoUseInAIKyrios
dcd42454bd fix(Spotify): Remove broken Spoof client patch (#5833) 2025-09-14 21:11:15 +04:00
LisoUseInAIKyrios
782353c18a refactor(Spoof video streams): Handle migration of default spoof client for users upgrading from very old patches 2025-09-14 18:06:40 +04:00
semantic-release-bot
b53b870e8f chore: Release v5.37.0-dev.2 [skip ci]
# [5.37.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.1...v5.37.0-dev.2) (2025-09-14)

### Bug Fixes

* Resolve patching with dev branch ([09b941a](09b941abf0))
2025-09-14 12:00:38 +00:00
LisoUseInAIKyrios
09b941abf0 fix: Resolve patching with dev branch 2025-09-14 15:58:05 +04:00
41 changed files with 567 additions and 404 deletions

View File

@@ -1,3 +1,75 @@
## [5.37.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.2...v5.37.1-dev.3) (2025-09-15)
### Bug Fixes
* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](https://github.com/ReVanced/revanced-patches/commit/abe3943f98fd86dcd74c7e07cf65d3c7fc24fef9))
## [5.37.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.1...v5.37.1-dev.2) (2025-09-15)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Support v397.1.0.52.81 ([#5855](https://github.com/ReVanced/revanced-patches/issues/5855)) ([f11d1ef](https://github.com/ReVanced/revanced-patches/commit/f11d1ef9907082512f139d4ab0e2e9f707de7e48))
## [5.37.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.0...v5.37.1-dev.1) (2025-09-15)
### Bug Fixes
* **YouTube Music - Spoof video streams:** Fix playback issues when using a cellular network ([fa04c8e](https://github.com/ReVanced/revanced-patches/commit/fa04c8eecfbdd0b6ed082b464ca9032536d71762))
# [5.37.0](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0) (2025-09-15)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](https://github.com/ReVanced/revanced-patches/commit/e6c79f13834c83fef04e4dee5e628cb0b9a27765))
* Resolve patching with dev branch ([09b941a](https://github.com/ReVanced/revanced-patches/commit/09b941abf0e8029999565082b02a88b5de507ec4))
* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](https://github.com/ReVanced/revanced-patches/commit/dcd42454bd5f87dddd720534f6120c4ef90063a3))
* **Viber - Hide ads:** Add constrain to known working version ([2db0948](https://github.com/ReVanced/revanced-patches/commit/2db0948beaf2b68391a1fe7f21e92d31c7df61e7))
* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](https://github.com/ReVanced/revanced-patches/commit/2a85a3b29092729ae16d1fd93803634ce5f08e95))
### Features
* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](https://github.com/ReVanced/revanced-patches/commit/0abfab79d7cda15bf17c53679fbfffb021662649))
# [5.37.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.5...v5.37.0-dev.6) (2025-09-15)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](https://github.com/ReVanced/revanced-patches/commit/e6c79f13834c83fef04e4dee5e628cb0b9a27765))
# [5.37.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.4...v5.37.0-dev.5) (2025-09-15)
### Bug Fixes
* **Viber - Hide ads:** Add constrain to known working version ([2db0948](https://github.com/ReVanced/revanced-patches/commit/2db0948beaf2b68391a1fe7f21e92d31c7df61e7))
# [5.37.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.3...v5.37.0-dev.4) (2025-09-14)
### Bug Fixes
* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](https://github.com/ReVanced/revanced-patches/commit/2a85a3b29092729ae16d1fd93803634ce5f08e95))
# [5.37.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.2...v5.37.0-dev.3) (2025-09-14)
### Bug Fixes
* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](https://github.com/ReVanced/revanced-patches/commit/dcd42454bd5f87dddd720534f6120c4ef90063a3))
# [5.37.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.1...v5.37.0-dev.2) (2025-09-14)
### Bug Fixes
* Resolve patching with dev branch ([09b941a](https://github.com/ReVanced/revanced-patches/commit/09b941abf0e8029999565082b02a88b5de507ec4))
# [5.37.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0-dev.1) (2025-09-14)

View File

@@ -1,3 +1,9 @@
dependencies {
compileOnly(project(":extensions:shared:library"))
compileOnly(project(":extensions:youtube:stub"))
compileOnly(libs.annotation)
}
android {
defaultConfig {
minSdk = 26

View File

@@ -0,0 +1,27 @@
package app.revanced.extension.music.patches.spoof;
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.VISIONOS;
import java.util.List;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
/**
* Injection point.
*/
public static void setClientOrderToUse() {
List<ClientType> availableClients = List.of(
ANDROID_VR_1_43_32,
ANDROID_VR_1_61_48,
VISIONOS
);
StreamingDataRequest.setClientOrderToUse(availableClients, ANDROID_VR_1_43_32);
}
}

View File

@@ -4,7 +4,6 @@ import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
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.SpoofiOSAvailability;
import app.revanced.extension.shared.spoof.ClientType;
@@ -31,9 +30,6 @@ public class BaseSettings {
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
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_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
// 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_NO_AUTH, 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));
}

View File

@@ -2,17 +2,21 @@ package app.revanced.extension.shared.spoof;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Locale;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.BaseSettings;
public enum ClientType {
/**
* Video not playable: Kids / Paid / Movie / Private / Age-restricted.
* This client can only be used when logged out.
*/
// https://dumps.tadiphone.dev/dumps/oculus/eureka
ANDROID_VR_NO_AUTH(
ANDROID_VR_1_61_48(
28,
"ANDROID_VR",
"com.google.android.apps.youtube.vr.oculus",
@@ -27,29 +31,32 @@ public enum ClientType {
"1.61.48",
false,
false,
"Android VR No auth"
"Android VR 1.61"
),
// Chromecast with Google TV 4K.
// https://dumps.tadiphone.dev/dumps/google/kirkwood
ANDROID_UNPLUGGED(
29,
"ANDROID_UNPLUGGED",
"com.google.android.apps.youtube.unplugged",
"Google",
"Google TV Streamer",
"Android",
"14",
"34",
"UTT3.240625.001.K5",
"132.0.6808.3",
"8.49.0",
true,
true,
"Android TV"
/**
* Uses non adaptive bitrate, which fixes audio stuttering with YT Music.
* Does not use AV1.
*/
ANDROID_VR_1_43_32(
ANDROID_VR_1_61_48.id,
ANDROID_VR_1_61_48.clientName,
Objects.requireNonNull(ANDROID_VR_1_61_48.packageName),
ANDROID_VR_1_61_48.deviceMake,
ANDROID_VR_1_61_48.deviceModel,
ANDROID_VR_1_61_48.osName,
ANDROID_VR_1_61_48.osVersion,
Objects.requireNonNull(ANDROID_VR_1_61_48.androidSdkVersion),
Objects.requireNonNull(ANDROID_VR_1_61_48.buildId),
"107.0.5284.2",
"1.43.32",
ANDROID_VR_1_61_48.requiresAuth,
ANDROID_VR_1_61_48.useAuth,
"Android VR 1.43"
),
// Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
// Google Pixel 9 Pro Fold
// https://dumps.tadiphone.dev/dumps/google/barbet
/**
* Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
* <a href="https://dumps.tadiphone.dev/dumps/google/barbet">Google Pixel 9 Pro Fold</a>
*/
ANDROID_CREATOR(
14,
"ANDROID_CREATOR",
@@ -66,42 +73,22 @@ public enum ClientType {
true,
"Android Creator"
),
IOS_UNPLUGGED(
33,
"IOS_UNPLUGGED",
"com.google.ios.youtubeunplugged",
/**
* Internal YT client for an unreleased YT client. May stop working at any time.
*/
VISIONOS(101,
"VISIONOS",
"Apple",
forceAVC()
// 11 Pro Max (last device with iOS 13)
? "iPhone12,5"
// 15 Pro Max
: "iPhone16,2",
"iOS",
forceAVC()
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
? "13.7.17H35"
: "18.2.22C152",
null,
null,
null,
// Version number should be a valid iOS release.
// https://www.ipa4fun.com/history/152043/
forceAVC()
// Some newer versions can also force AVC,
// but 6.45 is the last version that supports iOS 13.
? "6.45"
: "8.49",
true,
true,
forceAVC()
? "iOS TV Force AVC"
: "iOS TV"
"RealityDevice14,1",
"visionOS",
"1.3.21O771",
"0.1",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
false,
false,
"visionOS"
);
private static boolean forceAVC() {
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
}
/**
* YouTube
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
@@ -113,6 +100,7 @@ public enum ClientType {
/**
* App package name.
*/
@Nullable
private final String packageName;
/**
@@ -182,17 +170,20 @@ public enum ClientType {
*/
public final String friendlyName;
/**
* Android constructor.
*/
@SuppressWarnings("ConstantLocale")
ClientType(int id,
String clientName,
String packageName,
@NonNull String packageName,
String deviceMake,
String deviceModel,
String osName,
String osVersion,
@Nullable String androidSdkVersion,
@Nullable String buildId,
@Nullable String cronetVersion,
@NonNull String androidSdkVersion,
@NonNull String buildId,
@NonNull String cronetVersion,
String clientVersion,
boolean requiresAuth,
boolean useAuth,
@@ -213,31 +204,44 @@ public enum ClientType {
this.friendlyName = friendlyName;
Locale defaultLocale = Locale.getDefault();
if (androidSdkVersion == null) {
// Convert version from '18.2.22C152' into '18_2_22'
String userAgentOsVersion = osVersion
.replaceAll("(\\d+\\.\\d+\\.\\d+).*", "$1")
.replace(".", "_");
// https://github.com/mitmproxy/mitmproxy/issues/4836
this.userAgent = String.format("%s/%s (%s; U; CPU iOS %s like Mac OS X; %s)",
packageName,
clientVersion,
deviceModel,
userAgentOsVersion,
defaultLocale
);
} else {
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
packageName,
clientVersion,
osVersion,
defaultLocale,
deviceModel,
Objects.requireNonNull(buildId),
Objects.requireNonNull(cronetVersion)
);
}
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
packageName,
clientVersion,
osVersion,
defaultLocale,
deviceModel,
Objects.requireNonNull(buildId),
Objects.requireNonNull(cronetVersion)
);
Logger.printDebug(() -> "userAgent: " + this.userAgent);
}
@SuppressWarnings("ConstantLocale")
ClientType(int id,
String clientName,
String deviceMake,
String deviceModel,
String osName,
String osVersion,
String clientVersion,
String userAgent,
boolean requiresAuth,
boolean useAuth,
String friendlyName) {
this.id = id;
this.clientName = clientName;
this.deviceMake = deviceMake;
this.deviceModel = deviceModel;
this.osName = osName;
this.osVersion = osVersion;
this.clientVersion = clientVersion;
this.userAgent = userAgent;
this.requiresAuth = requiresAuth;
this.useAuth = useAuth;
this.friendlyName = friendlyName;
this.packageName = null;
this.androidSdkVersion = null;
this.buildId = null;
this.cronetVersion = null;
}
}

View File

@@ -10,6 +10,7 @@ import java.util.Map;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@@ -19,13 +20,25 @@ public class SpoofVideoStreamsPatch {
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();
private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.VISIONOS;
@Nullable
private static volatile AppLanguage languageOverride;
/**
* Any unreachable ip address. Used to intentionally fail requests.
* Domain used for internet connectivity verification.
* It has an empty response body and is only used to check for a 204 response code.
* <p>
* If an unreachable IP address (127.0.0.1) is used, no response code is provided.
* <p>
* YouTube handles unreachable IP addresses without issue.
* YouTube Music has an issue with waiting for the Cronet connect timeout of 30s on mobile networks.
* <p>
* Using a VPN or DNS can temporarily resolve this issue,
* But the ideal workaround is to avoid using an unreachable IP address.
*/
private static final String UNREACHABLE_HOST_URI_STRING = "https://127.0.0.0";
private static final Uri UNREACHABLE_HOST_URI = Uri.parse(UNREACHABLE_HOST_URI_STRING);
private static final String INTERNET_CONNECTION_CHECK_URI_STRING = "https://www.google.com/gen_204";
private static final Uri INTERNET_CONNECTION_CHECK_URI = Uri.parse(INTERNET_CONNECTION_CHECK_URI_STRING);
/**
* @return If this patch was included during patching.
@@ -34,10 +47,21 @@ public class SpoofVideoStreamsPatch {
return false; // Modified during patching.
}
public static boolean notSpoofingToAndroid() {
return !isPatchIncluded()
|| !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
public static boolean spoofingToClientWithNoMultiAudioStreams() {
return isPatchIncluded() && BaseSettings.SPOOF_VIDEO_STREAMS.get();
}
/**
* @param language Language override for non-authenticated requests. If this is null then
* {@link BaseSettings#SPOOF_VIDEO_STREAMS_LANGUAGE} is used.
*/
public static void setLanguageOverride(@Nullable AppLanguage language) {
languageOverride = language;
}
@Nullable
public static AppLanguage getLanguageOverride() {
return languageOverride;
}
/**
@@ -53,9 +77,9 @@ public class SpoofVideoStreamsPatch {
String path = playerRequestUri.getPath();
if (path != null && path.contains("get_watch")) {
Logger.printDebug(() -> "Blocking 'get_watch' by returning unreachable uri");
Logger.printDebug(() -> "Blocking 'get_watch' by returning internet connection check uri");
return UNREACHABLE_HOST_URI;
return INTERNET_CONNECTION_CHECK_URI;
}
} catch (Exception ex) {
Logger.printException(() -> "blockGetWatchRequest failure", ex);
@@ -77,9 +101,9 @@ public class SpoofVideoStreamsPatch {
String path = originalUri.getPath();
if (path != null && path.contains("initplayback")) {
Logger.printDebug(() -> "Blocking 'initplayback' by clearing query");
Logger.printDebug(() -> "Blocking 'initplayback' by returning internet connection check uri");
return originalUri.buildUpon().clearQuery().build().toString();
return INTERNET_CONNECTION_CHECK_URI_STRING;
}
} catch (Exception ex) {
Logger.printException(() -> "blockInitPlaybackRequest failure", ex);
@@ -252,16 +276,8 @@ public class SpoofVideoStreamsPatch {
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
}
}
public static final class SpoofiOSAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
// Since all current clients are un-authenticated, this works for all spoof clients.
return BaseSettings.SPOOF_VIDEO_STREAMS.get();
}
}
}

View File

@@ -1,5 +1,7 @@
package app.revanced.extension.shared.spoof.requests;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import org.json.JSONException;
import org.json.JSONObject;
@@ -10,8 +12,10 @@ import java.util.Locale;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
final class PlayerRoutes {
static final Route.CompiledRoute GET_STREAMING_DATA = new Route(
@@ -37,14 +41,16 @@ final class PlayerRoutes {
try {
JSONObject context = new JSONObject();
// Can override default language only if no login is used.
// Could use preferred audio for all clients that do not login,
// but if this is a fall over client it will set the language even though
// the audio language is not selectable in the UI.
ClientType userSelectedClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
Locale streamLocale = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getLocale()
: Locale.getDefault();
AppLanguage language = SpoofVideoStreamsPatch.getLanguageOverride();
if (language == null || BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ANDROID_VR_1_43_32) {
// Force original audio has not overrode the language.
// Or if YT has fallen over to the very last client (VR 1.43), then always
// use the app language because forcing an audio stream of specific languages
// can sometimes fail so it's better to try and load something rather than nothing.
language = BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get();
}
//noinspection ExtractMethodRecommender
Locale streamLocale = language.getLocale();
JSONObject client = new JSONObject();
client.put("deviceMake", clientType.deviceMake);

View File

@@ -35,21 +35,27 @@ import app.revanced.extension.shared.spoof.ClientType;
*/
public class StreamingDataRequest {
private static final ClientType[] CLIENT_ORDER_TO_USE;
private static volatile ClientType[] clientOrderToUse = ClientType.values();
static {
ClientType[] allClientTypes = ClientType.values();
ClientType preferredClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
public static void setClientOrderToUse(List<ClientType> availableClients, ClientType preferredClient) {
Objects.requireNonNull(preferredClient);
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
CLIENT_ORDER_TO_USE[0] = preferredClient;
int availableClientSize = availableClients.size();
if (!availableClients.contains(preferredClient)) {
availableClientSize++;
}
clientOrderToUse = new ClientType[availableClientSize];
clientOrderToUse[0] = preferredClient;
int i = 1;
for (ClientType c : allClientTypes) {
for (ClientType c : availableClients) {
if (c != preferredClient) {
CLIENT_ORDER_TO_USE[i++] = c;
clientOrderToUse[i++] = c;
}
}
Logger.printDebug(() -> "Available spoof clients: " + Arrays.toString(clientOrderToUse));
}
private static final String AUTHORIZATION_HEADER = "Authorization";
@@ -193,9 +199,9 @@ public class StreamingDataRequest {
// Retry with different client if empty response body is received.
int i = 0;
for (ClientType clientType : CLIENT_ORDER_TO_USE) {
for (ClientType clientType : clientOrderToUse) {
// Show an error if the last client type fails, or if debug is enabled then show for all attempts.
final boolean showErrorToast = (++i == CLIENT_ORDER_TO_USE.length) || debugEnabled;
final boolean showErrorToast = (++i == clientOrderToUse.length) || debugEnabled;
HttpURLConnection connection = send(clientType, videoId, playerHeaders, showErrorToast);
if (connection != null) {

View File

@@ -1,7 +1,7 @@
package app.revanced.extension.youtube.patches;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings;
@@ -11,16 +11,20 @@ public class ForceOriginalAudioPatch {
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
/**
* If the conditions to use this patch were present when the app launched.
* Injection point.
*/
public static boolean PATCH_AVAILABLE = SpoofVideoStreamsPatch.notSpoofingToAndroid();
public static final class ForceOriginalAudioAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
// Check conditions of launch and now. Otherwise if spoofing is changed
// without a restart the setting will show as available when it's not.
return PATCH_AVAILABLE && SpoofVideoStreamsPatch.notSpoofingToAndroid();
public static void setPreferredLanguage() {
if (Settings.FORCE_ORIGINAL_AUDIO.get()) {
// None of the current spoof clients support audio track menu,
// And all are un-authenticated and can request any language code
// (authenticated requests ignore the language code and always use the account language).
// To still support force original audio, if it's enabled then pick 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
// Android VR is spoofing.
AppLanguage override = AppLanguage.SV;
Logger.printDebug(() -> "Setting language override: " + override);
SpoofVideoStreamsPatch.setLanguageOverride(override);
}
}

View File

@@ -9,13 +9,13 @@ import app.revanced.extension.youtube.shared.ShortsPlayerState;
public class PlayerFlyoutMenuItemsFilter extends Filter {
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
private static final boolean AVAILABLE_ON_LAUNCH = SpoofVideoStreamsPatch.notSpoofingToAndroid();
private static final boolean AVAILABLE_ON_LAUNCH = !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
@Override
public boolean isAvailable() {
// Check conditions of launch and now. Otherwise if spoofing is changed
// without a restart the setting will show as available when it's not.
return AVAILABLE_ON_LAUNCH && SpoofVideoStreamsPatch.notSpoofingToAndroid();
return AVAILABLE_ON_LAUNCH && !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
}
}

View File

@@ -0,0 +1,32 @@
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_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.VISIONOS;
import java.util.List;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
/**
* Injection point.
*/
public static void setClientOrderToUse() {
List<ClientType> availableClients = List.of(
ANDROID_VR_1_61_48,
ANDROID_CREATOR,
VISIONOS,
// VR 1.43 must be last as spoof streaming data handles it slightly differently.
ANDROID_VR_1_43_32
);
StreamingDataRequest.setClientOrderToUse(availableClients,
BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
}
}

View File

@@ -12,7 +12,6 @@ import static app.revanced.extension.youtube.patches.ChangeHeaderPatch.HeaderLog
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.ChangeStartPageTypeAvailability;
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
@@ -75,7 +74,7 @@ public class Settings extends BaseSettings {
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
// Audio
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, true);
// Ads
public static final BooleanSetting HIDE_CREATOR_STORE_SHELF = new BooleanSetting("revanced_hide_creator_store_shelf", TRUE);

View File

@@ -1,36 +0,0 @@
package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import app.revanced.extension.youtube.patches.ForceOriginalAudioPatch;
@SuppressWarnings({"deprecation", "unused"})
public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
{
if (!ForceOriginalAudioPatch.PATCH_AVAILABLE) {
// Show why force audio is not available.
String summary = str("revanced_force_original_audio_not_available");
setSummary(summary);
setSummaryOn(summary);
setSummaryOff(summary);
}
}
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ForceOriginalAudioSwitchPreference(Context context) {
super(context);
}
}

View File

@@ -12,8 +12,8 @@ import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
public class HideAudioFlyoutMenuPreference extends SwitchPreference {
{
// Audio menu is not available if spoofing to Android client type.
if (!SpoofVideoStreamsPatch.notSpoofingToAndroid()) {
// Audio menu is not available if spoofing to most client types.
if (SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
String summary = str("revanced_hide_player_flyout_audio_track_not_available");
setSummary(summary);
setSummaryOn(summary);

View File

@@ -78,20 +78,17 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
Logger.printDebug(() -> "Updating spoof stream side effects preference");
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
String key = "revanced_spoof_video_streams_about_" +
(clientType == ClientType.IOS_UNPLUGGED
? "ios_tv"
: "android");
String title = str(key + "_title");
String summary = str(key + "_summary");
// Android VR supports AV1 but all other clients do not.
if (clientType != ClientType.ANDROID_VR_NO_AUTH) {
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
}
String title = 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) {
summary = str("revanced_spoof_video_streams_about_experimental")
+ '\n' + summary
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
}
setTitle(title);
setSummary(summary);
}

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.37.0-dev.1
version = 5.37.1-dev.3

View File

@@ -23,7 +23,7 @@ internal val tabCreateButtonsLoopEndFingerprint = fingerprint {
Opcode.IPUT_OBJECT,
// Injection Jump
Opcode.ADD_INT_LIT8, //Increase Index
Opcode.GOTO_16 // Jump to loopStart
Opcode.GOTO // Jump to loopStart
// LoopEnd
)
}

View File

@@ -15,7 +15,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
description = "Hides navigation bar buttons, such as the Reels and Create button.",
use = false
) {
compatibleWith("com.instagram.android")
compatibleWith("com.instagram.android"("397.1.0.52.81"))
val hideReels by booleanOption(
key = "hideReels",

View File

@@ -1,12 +1,20 @@
package app.revanced.patches.music.misc.spoof
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint
import app.revanced.patches.music.playservice.is_7_33_or_greater
import app.revanced.patches.music.playservice.is_8_11_or_greater
import app.revanced.patches.music.playservice.is_8_15_or_greater
import app.revanced.patches.music.playservice.versionCheckPatch
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;"
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
fixMediaFetchHotConfigChanges = { true },
fixMediaFetchHotConfigAlternativeChanges = { is_8_11_or_greater && !is_8_15_or_greater },
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater },
block = {
compatibleWith(
"com.google.android.apps.youtube.music"(
@@ -14,9 +22,12 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
)
)
dependsOn(versionCheckPatch, userAgentClientSpoofPatch)
dependsOn(sharedExtensionPatch, versionCheckPatch, userAgentClientSpoofPatch)
},
fixMediaFetchHotConfigChanges = { true },
fixMediaFetchHotConfigAlternativeChanges = { is_8_11_or_greater && !is_8_15_or_greater },
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater }
executeBlock = {
musicActivityOnCreateFingerprint.method.addInstruction(
1, // Must use 1 index so context is set by extension patch.
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
)
}
)

View File

@@ -43,7 +43,7 @@ fun spoofVideoStreamsPatch(
) {
block()
dependsOn(sharedExtensionPatch, addResourcesPatch)
dependsOn(addResourcesPatch)
execute {
// region Enable extension helper method used by other patches

View File

@@ -187,11 +187,16 @@ val customThemePatch = resourcePatch(
}
// Login screen gradient.
document("res/drawable/start_screen_gradient.xml").use { document ->
val gradientNode = document.getElementsByTagName("gradient").item(0) as Element
try {
document("res/drawable/start_screen_gradient.xml").use { document ->
val gradientNode = document.getElementsByTagName("gradient").item(0) as Element
gradientNode.setAttribute("android:startColor", "@color/gray_7")
gradientNode.setAttribute("android:endColor", "@color/gray_7")
gradientNode.setAttribute("android:startColor", "@color/gray_7")
gradientNode.setAttribute("android:endColor", "@color/gray_7")
}
} catch (_: Exception) {
// Fails for 9.0.66+
// printWarn("Failed to locate start_screen_gradient.xml, skipping modification.")
}
}
}

View File

@@ -12,9 +12,9 @@ import app.revanced.util.returnEarly
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/misc/fix/SpoofClientPatch;"
@Deprecated("Patch no longer functions")
@Suppress("unused")
val spoofClientPatch = bytecodePatch(
name = "Spoof client",
description = "Spoofs the client to fix various functions of the app.",
) {
val requestListenerPort by intOption(

View File

@@ -8,7 +8,7 @@ val hideAdsPatch = bytecodePatch(
name = "Hide Ads",
description = "Hides ad banners between chats.",
) {
compatibleWith("com.viber.voip")
compatibleWith("com.viber.voip"("25.9.2.0"))
execute {
// Return 1 (true) indicating ads should be disabled.

View File

@@ -89,7 +89,7 @@ val downloadsPatch = bytecodePatch(
// Main activity is used to launch downloader intent.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
)

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.layout.seekbar
import app.revanced.patcher.fingerprint
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.util.containsLiteralInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
@@ -103,7 +104,7 @@ internal val launchScreenLayoutTypeFingerprint = fingerprint {
custom { method, _ ->
val firstParameter = method.parameterTypes.firstOrNull()
// 19.25 - 19.45
(firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
(firstParameter == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|| firstParameter == "Landroid/app/Activity;") // 19.46+
&& method.containsLiteralInstruction(launchScreenLayoutTypeLotteFeatureFlag)
}

View File

@@ -68,7 +68,7 @@ val shortsAutoplayPatch = bytecodePatch(
// Main activity is used to check if app is in pip mode.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V",
)

View File

@@ -90,8 +90,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
// Activity is used as the context to launch an Intent.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
"invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->" +
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
"setMainActivity(Landroid/app/Activity;)V",
)

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.layout.theme
import app.revanced.patcher.fingerprint
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -37,6 +38,6 @@ internal val splashScreenStyleFingerprint = fingerprint {
parameters("Landroid/os/Bundle;")
literal { SPLASH_SCREEN_STYLE_FEATURE_FLAG }
custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -40,9 +40,7 @@ val announcementsPatch = bytecodePatch(
)
mainActivityOnCreateFingerprint.method.addInstruction(
// Insert index must be greater than the insert index used by GmsCoreSupport,
// as both patch the same method and GmsCore check should be first.
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
)
}

View File

@@ -34,12 +34,7 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
addResources("youtube", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
mainActivityOnCreateFingerprint.method.addInstruction(
// FIXME: Insert index must be greater than the insert index used by GmsCoreSupport,
// as both patch the same method and GmsCoreSupport check should be first,
// but the patch does not depend on GmsCoreSupport, so it should not be possible to enforce this
// unless a third patch is added that this patch and GmsCoreSupport depend on to manage
// the order of the patches.
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
)
}

View File

@@ -3,4 +3,5 @@ package app.revanced.patches.youtube.misc.extension
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.extension.hooks.*
val sharedExtensionPatch = sharedExtensionPatch("youtube", applicationInitHook)
val sharedExtensionPatch = sharedExtensionPatch("youtube",
applicationInitHook, applicationInitOnCrateHook)

View File

@@ -1,11 +1,23 @@
package app.revanced.patches.youtube.misc.extension.hooks
import app.revanced.patches.shared.misc.extension.extensionHook
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
/**
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
*/
// Extension context is the Activity itself.
internal val applicationInitHook = extensionHook {
// Does _not_ resolve to the YouTube main activity.
// Required as some hooked code runs before the main activity is launched.
strings("Application creation", "Application.onCreate")
}
internal val applicationInitOnCrateHook = extensionHook {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -127,8 +127,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
// Litho filtering based on navigation tab before the tab is updated.
mainActivityOnBackPressedFingerprint.method.addInstruction(
0,
"invoke-static { p0 }, " +
"$EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
)
// Hook the search bar.

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.misc.spoof
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.shared.misc.settings.preference.ListPreference
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
@@ -13,56 +14,69 @@ import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"19.43.41",
"19.47.53",
"20.07.39",
"20.12.46",
"20.13.41",
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;"
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
block = {
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"19.43.41",
"19.47.53",
"20.07.39",
"20.12.46",
"20.13.41",
)
)
)
dependsOn(
userAgentClientSpoofPatch,
settingsPatch,
versionCheckPatch
)
}, {
is_19_34_or_greater
}, {
// In 20.14 the flag was merged with 20.03 start playback flag.
is_20_10_or_greater && !is_20_14_or_greater
}, {
is_20_03_or_greater
}, {
addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch")
dependsOn(
userAgentClientSpoofPatch,
settingsPatch,
versionCheckPatch
)
},
fixMediaFetchHotConfigChanges = {
is_19_34_or_greater
},
fixMediaFetchHotConfigAlternativeChanges = {
// In 20.14 the flag was merged with 20.03 start playback flag.
is_20_10_or_greater && !is_20_14_or_greater
},
fixParsePlaybackResponseFeatureFlag = {
is_20_03_or_greater
},
executeBlock = {
addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch")
PreferenceScreen.MISC.addPreferences(
PreferenceScreenPreference(
key = "revanced_spoof_video_streams_screen",
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_video_streams"),
ListPreference("revanced_spoof_video_streams_client_type"),
NonInteractivePreference(
// Requires a key and title but the actual text is chosen at runtime.
key = "revanced_spoof_video_streams_about_android",
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
),
ListPreference(
key = "revanced_spoof_video_streams_language",
// Language strings are declared in Setting patch.
entriesKey = "revanced_language_entries",
entryValuesKey = "revanced_language_entry_values",
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
),
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
),
),
)
})
PreferenceScreen.MISC.addPreferences(
PreferenceScreenPreference(
key = "revanced_spoof_video_streams_screen",
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_video_streams"),
ListPreference("revanced_spoof_video_streams_client_type"),
NonInteractivePreference(
// Requires a key and title but the actual text is chosen at runtime.
key = "revanced_spoof_video_streams_about_android",
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
),
ListPreference(
key = "revanced_spoof_video_streams_language",
// Language strings are declared in Setting patch.
entriesKey = "revanced_language_entries",
entryValuesKey = "revanced_language_entry_values",
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
),
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
)
)
)
mainActivityOnCreateFingerprint.method.addInstruction(
0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
)
}
)

View File

@@ -4,6 +4,8 @@ import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
internal val conversionContextFingerprintToString = fingerprint {
parameters()
strings(
@@ -48,7 +50,7 @@ internal val mainActivityConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters()
custom { _, classDef ->
classDef.endsWith("/MainActivity;")
classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}
@@ -57,7 +59,7 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint {
returns("V")
parameters()
custom { method, classDef ->
method.name == "onBackPressed" && classDef.endsWith("/MainActivity;")
method.name == "onBackPressed" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}
@@ -65,7 +67,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.video.audio
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@@ -14,6 +15,7 @@ import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
import app.revanced.util.findMethodFromToString
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertLiteralOverride
@@ -55,10 +57,12 @@ val forceOriginalAudioPatch = bytecodePatch(
addResources("youtube", "video.audio.forceOriginalAudioPatch")
PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
key = "revanced_force_original_audio",
tag = "app.revanced.extension.youtube.settings.preference.ForceOriginalAudioSwitchPreference"
)
SwitchPreference("revanced_force_original_audio")
)
mainActivityOnCreateFingerprint.method.addInstruction(
0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setPreferredLanguage()V"
)
// Disable feature flag that ignores the default track flag

View File

@@ -96,13 +96,13 @@ Toca el botón continuar y permite los cambios de optimización."</string>
<string name="revanced_settings_screen_07_seekbar_title">Barra de progreso</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Controles de deslizamiento</string>
<string name="revanced_settings_screen_11_misc_title">Otros</string>
<string name="revanced_settings_screen_12_video_title">Video</string>
<string name="revanced_settings_screen_12_video_title">Vídeo</string>
<string name="revanced_restore_old_settings_menus_title">Restaurar menús de configuración antiguos</string>
<string name="revanced_restore_old_settings_menus_summary_on">Se muestran los menús de configuración antiguos</string>
<string name="revanced_restore_old_settings_menus_summary_off">No se muestran los menús de configuración antiguos</string>
<string name="revanced_restore_old_settings_menus_summary_on">Los menús de configuración antiguos son visibles</string>
<string name="revanced_restore_old_settings_menus_summary_off">Los menús de configuración antiguos están ocultos</string>
<string name="revanced_settings_search_history_title">Mostrar el historial de búsqueda de ajustes</string>
<string name="revanced_settings_search_history_summary_on">El historial de búsqueda de los ajustes es visible</string>
<string name="revanced_settings_search_history_summary_off">El historial de búsqueda de ajustes no se muestra</string>
<string name="revanced_settings_search_history_summary_on">El historial de búsqueda de los ajustes es visible</string>
<string name="revanced_settings_search_history_summary_off">El historial de búsqueda de ajustes está oculto</string>
</patch>
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
<string name="revanced_shorts_disable_background_playback_title">Desactivar la reproducción en segundo plano de Shorts</string>
@@ -151,19 +151,19 @@ No se le notificará de ningún evento inesperado."</string>
<string name="revanced_hide_artist_cards_summary_off">Se muestran las tarjetas de artista</string>
<string name="revanced_hide_chips_shelf_title">Ocultar \"Más como esto\"</string>
<string name="revanced_hide_chips_shelf_summary_on">\"Más como esto\" está oculto</string>
<string name="revanced_hide_chips_shelf_summary_off">\"Más como esto\" está habilitado</string>
<string name="revanced_hide_chips_shelf_summary_off">\"Más como esto\" es visible</string>
<string name="revanced_hide_community_posts_title">Ocultar publicaciones de comunidad</string>
<string name="revanced_hide_community_posts_summary_on">Las publicaciones de la comunidad están ocultas</string>
<string name="revanced_hide_community_posts_summary_off">Se muestran las publicaciones de la comunidad</string>
<string name="revanced_hide_community_posts_summary_off">Las publicaciones de la comunidad se muestran</string>
<string name="revanced_hide_compact_banner_title">Ocultar banners compactos</string>
<string name="revanced_hide_compact_banner_summary_on">Los banners compactos están ocultos</string>
<string name="revanced_hide_compact_banner_summary_off">Se muestran los banners compactos</string>
<string name="revanced_hide_crowdfunding_box_title">Ocultar caja de Crowdfunding</string>
<string name="revanced_hide_crowdfunding_box_summary_on">La caja de Crowdfunding está oculta</string>
<string name="revanced_hide_crowdfunding_box_summary_off">La caja de Crowdfunding es visible</string>
<string name="revanced_hide_crowdfunding_box_summary_off">La caja de Crowdfunding es visible</string>
<string name="revanced_hide_expandable_card_title">Ocultar tarjeta expandible</string>
<string name="revanced_hide_expandable_card_summary_on">Tarjeta expandible debajo de los videos oculta</string>
<string name="revanced_hide_expandable_card_summary_off">Tarjeta expandible debajo de los videos visible</string>
<string name="revanced_hide_expandable_card_summary_on">La tarjeta expandible debajo de los vídeos está oculta</string>
<string name="revanced_hide_expandable_card_summary_off">La tarjeta expandible debajo de los vídeos es visible</string>
<string name="revanced_hide_floating_microphone_button_title">Ocultar botón de micrófono flotante</string>
<string name="revanced_hide_floating_microphone_button_summary_on">El botón flotante del micrófono en la búsqueda está oculto</string>
<string name="revanced_hide_floating_microphone_button_summary_off">Se muestra el botón flotante del micrófono en la búsqueda</string>
@@ -175,42 +175,42 @@ No se le notificará de ningún evento inesperado."</string>
• Más relevantes
• Compras
• Ver de nuevo"</string>
<string name="revanced_hide_horizontal_shelves_summary_off">Los estantes horizontales están visibles</string>
<string name="revanced_hide_horizontal_shelves_summary_off">Los estantes horizontales son visibles</string>
<string name="revanced_hide_image_shelf_title">Ocultar estantería de imágenes</string>
<string name="revanced_hide_image_shelf_summary_on">Estantería de imágenes en los resultados de búsqueda oculta</string>
<string name="revanced_hide_image_shelf_summary_off">Estantería de imágenes en los resultados de búsqueda visible</string>
<string name="revanced_hide_image_shelf_summary_on">La estantería de imágenes en los resultados de búsqueda está oculta</string>
<string name="revanced_hide_image_shelf_summary_off">La estantería de imágenes en los resultados de búsqueda es visible</string>
<string name="revanced_hide_latest_posts_title">Ocultar últimas publicaciones</string>
<string name="revanced_hide_latest_posts_summary_on">Las últimas publicaciones están ocultas</string>
<string name="revanced_hide_latest_posts_summary_off">Se muestran las últimas publicaciones</string>
<string name="revanced_hide_mix_playlists_title">Ocultar lista de reproducción Mix</string>
<string name="revanced_hide_mix_playlists_summary_on">La lista de reproducción Mix está oculta</string>
<string name="revanced_hide_mix_playlists_summary_off">La lista de reproducción Mix es visible</string>
<string name="revanced_hide_mix_playlists_summary_on">Las listas de reproducción Mix están ocultas</string>
<string name="revanced_hide_mix_playlists_summary_off">La lista de reproducción Mix es visible</string>
<string name="revanced_hide_movies_section_title">Ocultar sección de películas</string>
<string name="revanced_hide_movies_section_summary_on">La sección de películas está oculta</string>
<string name="revanced_hide_movies_section_summary_off">La sección de películas es visible</string>
<string name="revanced_hide_movies_section_summary_off">La sección de películas es visible</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<string name="revanced_hide_notify_me_button_title">Ocultar el botón \'Notificarme\'</string>
<string name="revanced_hide_notify_me_button_title">Ocultar el botón \"Notificarme\"</string>
<string name="revanced_hide_notify_me_button_summary_on">El botón Notificarme está oculto</string>
<string name="revanced_hide_notify_me_button_summary_off">El botón Notificarme es visible</string>
<string name="revanced_hide_notify_me_button_summary_off">El botón Notificarme es visible</string>
<string name="revanced_hide_playables_title">Ocultar jugables</string>
<string name="revanced_hide_playables_summary_on">Los jugables están ocultos</string>
<string name="revanced_hide_playables_summary_off">Los jugables están visibles</string>
<string name="revanced_hide_playables_summary_off">Los jugables son visibles</string>
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. -->
<string name="revanced_hide_show_more_button_title">Ocultar botón \'Mostrar más\'</string>
<string name="revanced_hide_show_more_button_summary_on">El botón Mostrar más en los resultados de búsqueda está oculto</string>
<string name="revanced_hide_show_more_button_summary_off">El botón Mostrar más en los resultados de búsqueda es visible</string>
<string name="revanced_hide_show_more_button_summary_off">El botón Mostrar más en los resultados de búsqueda es visible</string>
<string name="revanced_hide_surveys_title">Ocultar encuestas</string>
<string name="revanced_hide_surveys_summary_on">Las encuestas están ocultas</string>
<string name="revanced_hide_surveys_summary_off">Las encuestas están visibles</string>
<string name="revanced_hide_surveys_summary_off">Las encuestas son visibles</string>
<string name="revanced_hide_ticket_shelf_title">Ocultar estantes de tickets</string>
<string name="revanced_hide_ticket_shelf_summary_on">El estante de tickets está oculto</string>
<string name="revanced_hide_ticket_shelf_summary_off">El estante de boletos es visible</string>
<string name="revanced_hide_ticket_shelf_summary_on">La estantería de tickets está oculta</string>
<string name="revanced_hide_ticket_shelf_summary_off">La estantería de tickets es visible</string>
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
<string name="revanced_hide_video_recommendation_labels_title">Ocultar etiquetas de recomendación de vídeo</string>
<string name="revanced_hide_video_recommendation_labels_summary_on">Las etiquetas \"La gente también vio\" y \"También te puede gustar\" en los resultados de búsqueda están ocultas</string>
<string name="revanced_hide_video_recommendation_labels_summary_off">Las etiquetas \"La gente también vio\" y \"También te puede gustar\" en los resultados de búsqueda están visibles</string>
<string name="revanced_hide_video_recommendation_labels_summary_off">Las etiquetas \"La gente también vio\" y \"También te puede gustar\" en los resultados de búsqueda son visibles</string>
<!-- https://logos.fandom.com/wiki/YouTube/Yoodles -->
<string name="revanced_hide_doodles_title">Ocultar YouTube Doodles</string>
<string name="revanced_hide_doodles_summary_on">La animación de los Doodles de YouTube en el logotipo está oculta</string>
@@ -219,10 +219,10 @@ No se le notificará de ningún evento inesperado."</string>
Si un doodle se está mostrando actualmente en tu región y este ajuste de ocultación está activado, la barra de filtro situada debajo de la barra de búsqueda también estará oculta."</string>
<string name="revanced_hide_channel_bar_title">Ocultar barra de canal</string>
<string name="revanced_hide_channel_bar_summary_on">Barra de canales oculta</string>
<string name="revanced_hide_channel_bar_summary_on">La barra de canales está oculta</string>
<string name="revanced_hide_channel_bar_summary_off">Barra de canales mostrada</string>
<string name="revanced_hide_channel_watermark_title">Ocultar marca de agua del canal</string>
<string name="revanced_hide_channel_watermark_summary_on">Marca de agua oculta</string>
<string name="revanced_hide_channel_watermark_summary_on">La marca de agua está oculta</string>
<string name="revanced_hide_channel_watermark_summary_off">Marca de agua mostrada</string>
<string name="revanced_hide_emergency_box_title">Ocultar cajas de emergencia</string>
<string name="revanced_hide_emergency_box_summary_on">Las cajas de emergencia están ocultas</string>
@@ -232,17 +232,17 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<string name="revanced_hide_info_panels_summary_off">Los paneles de información se muestran</string>
<!-- 'Join' should be translated using the same localized wording YouTube displays.
This appears in the video player for certain videos. -->
<string name="revanced_hide_join_membership_button_title">Ocultar el botón Unirse</string>
<string name="revanced_hide_join_membership_button_title">Ocultar el botón \"Unirse\"</string>
<string name="revanced_hide_join_membership_button_summary_on">El botón Unirse está oculto</string>
<string name="revanced_hide_join_membership_button_summary_off">El botón Unirse es visible</string>
<string name="revanced_hide_join_membership_button_summary_off">El botón Unirse es visible</string>
<string name="revanced_hide_medical_panels_title">Ocultar paneles médicos</string>
<string name="revanced_hide_medical_panels_summary_on">Los paneles médicos están ocultos</string>
<string name="revanced_hide_medical_panels_summary_off">Se muestran paneles médicos</string>
<string name="revanced_hide_quick_actions_title">Ocultar acciones rápidas</string>
<string name="revanced_hide_quick_actions_summary_on">Acciones rápidas en pantalla completa ocultas</string>
<string name="revanced_hide_quick_actions_summary_on">Las rápidas en pantalla completa están ocultas</string>
<string name="revanced_hide_quick_actions_summary_off">Acciones rápidas en pantalla completa visibles</string>
<string name="revanced_hide_related_videos_title">Ocultar videos relacionados</string>
<string name="revanced_hide_related_videos_summary_on">Videos relacionados en acciones rápidas ocultos</string>
<string name="revanced_hide_related_videos_summary_on">Los vídeos relacionados en acciones rápidas están ocultos</string>
<string name="revanced_hide_related_videos_summary_off">Videos relacionados en acciones rápidas visibles</string>
<string name="revanced_hide_subscribers_community_guidelines_title">Ocultar las directrices para suscriptores</string>
<string name="revanced_hide_subscribers_community_guidelines_summary_on">Las pautas comunitarias de los suscriptores están ocultas</string>
@@ -250,7 +250,7 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<string name="revanced_hide_timed_reactions_title">Ocultar reacciones temporizadas</string>
<string name="revanced_hide_timed_reactions_summary_on">Las reacciones temporizadas están ocultas</string>
<string name="revanced_hide_timed_reactions_summary_off">Se muestran reacciones temporizadas</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">Ocultar \"Resumen de video generado por IA\"</string>
<string name="revanced_hide_ai_generated_video_summary_section_title">Ocultar \"Resumen de vídeo generado por IA\"</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">La sección de resumen de vídeo generada por IA está oculta</string>
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Sección de resumen de vídeo generada por IA está mostrada</string>
<string name="revanced_hide_ask_section_title">Ocultar pregunta</string>
@@ -285,7 +285,7 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Oculto en feeds</string>
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Visible en feeds</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Ocultar en vídeos relacionados</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Escondido en videos relacionados</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Oculto en vídeos relacionados</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Mostrar en vídeos relacionados</string>
<string name="revanced_hide_filter_bar_feed_in_search_title">Ocultar en los resultados de búsqueda</string>
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Oculto en los resultados de búsqueda</string>
@@ -298,29 +298,29 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
<string name="revanced_hide_for_you_shelf_title">Ocultar la sección \"Para ti\"</string>
<string name="revanced_hide_for_you_shelf_summary_on">La estantería \"Para ti\" está oculta</string>
<string name="revanced_hide_for_you_shelf_summary_off">La estantería \"Para ti\" es visible</string>
<string name="revanced_hide_for_you_shelf_summary_off">La estantería \"Para ti\" es visible</string>
<string name="revanced_hide_links_preview_title">Ocultar vista previa de enlaces</string>
<string name="revanced_hide_links_preview_summary_on">Vista previa de enlaces oculta</string>
<string name="revanced_hide_links_preview_summary_on">La vista previa de enlaces está oculta</string>
<string name="revanced_hide_links_preview_summary_off">Vista previa de enlaces visible</string>
<string name="revanced_hide_members_shelf_title">Ocultar estantería de miembros</string>
<string name="revanced_hide_members_shelf_summary_on">Estantería de miembros oculta</string>
<string name="revanced_hide_members_shelf_summary_off">El estante de miembros se muestra</string>
<string name="revanced_hide_members_shelf_summary_on">La estantería de miembros está oculta</string>
<string name="revanced_hide_members_shelf_summary_off">La estantería de miembros se muestra</string>
<!-- 'Visit Community' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_visit_community_button_title">Ocultar el botón \"Visitar comunidad\"</string>
<string name="revanced_hide_visit_community_button_summary_on">El botón Visitar comunidad está oculto</string>
<string name="revanced_hide_visit_community_button_summary_off">El botón \"Visitar comunidad\" es visible</string>
<string name="revanced_hide_visit_community_button_summary_off">El botón \"Visitar comunidad\" es visible</string>
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_visit_store_button_title">Ocultar el botón \'Visitar tienda\' en las páginas del canal</string>
<string name="revanced_hide_visit_store_button_summary_on">El botón \"Visitar tienda\" está oculto</string>
<string name="revanced_hide_visit_store_button_summary_off">El botón \"Visitar tienda\" es visible</string>
<string name="revanced_hide_visit_store_button_summary_off">El botón \"Visitar tienda\" es visible</string>
<string name="revanced_comments_screen_title">Comentarios</string>
<string name="revanced_comments_screen_summary">Ocultar o mostrar los componentes de sección de comentarios</string>
<string name="revanced_hide_comments_ai_chat_summary_title">Ocultar resumen de chat de IA</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_on">El resumen del chat de IA está oculto</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">El resumen del chat de IA es visible</string>
<string name="revanced_hide_comments_ai_chat_summary_summary_off">El resumen del chat de IA es visible</string>
<string name="revanced_hide_comments_ai_summary_title">Ocultar el resumen de los comentarios de la IA</string>
<string name="revanced_hide_comments_ai_summary_summary_on">El resumen de comentarios de IA está oculto</string>
<string name="revanced_hide_comments_ai_summary_summary_off">El resumen de comentarios de IA es visible</string>
<string name="revanced_hide_comments_ai_summary_summary_off">El resumen de comentarios de IA es visible</string>
<string name="revanced_hide_comments_channel_guidelines_title">Ocultar directrices del canal</string>
<string name="revanced_hide_comments_channel_guidelines_summary_on">Las directrices del canal están ocultas</string>
<string name="revanced_hide_comments_channel_guidelines_summary_off">Las directrices del canal se muestran</string>
@@ -357,14 +357,14 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<string name="revanced_hide_keyword_content_screen_title">Ocultar contenido de palabra clave</string>
<string name="revanced_hide_keyword_content_screen_summary">Ocultar videos de búsqueda y feed usando filtros de palabras clave</string>
<string name="revanced_hide_keyword_content_home_title">Ocultar videos domésticos por palabras clave</string>
<string name="revanced_hide_keyword_content_home_summary_on">Los videos en la pestaña \'Inicio\' son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_home_summary_off">Los videos en la pestaña \'Inicio\' no son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_home_summary_on">Los vídeos en la pestaña \'Inicio\' son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_home_summary_off">Los vídeos en la pestaña \'Inicio\' no son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_search_title">Ocultar resultados de búsqueda por palabras clave</string>
<string name="revanced_hide_keyword_content_search_summary_on">Los resultados de la búsqueda son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_search_summary_off">Los resultados de la búsqueda no son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_subscriptions_title">Ocultar vídeos de suscripción por palabras clave</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_on">Los videos en la pestaña \'Suscripciones\' son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_off">Los videos en la pestaña \'Suscripciones\' no son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_on">Los vídeos en la pestaña \'Suscripciones\' son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_off">Los vídeos en la pestaña \'Suscripciones\' no son filtrados por palabras clave</string>
<string name="revanced_hide_keyword_content_phrases_title">Palabras clave a ocultar</string>
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
@@ -392,11 +392,11 @@ Limitaciones
</patch>
<patch id="ad.general.hideAdsResourcePatch">
<string name="revanced_hide_creator_store_shelf_title">Ocultar estantería de la tienda del creador</string>
<string name="revanced_hide_creator_store_shelf_summary_on">El estante de la tienda del creador debajo del reproductor de vídeo está oculto</string>
<string name="revanced_hide_creator_store_shelf_summary_off">Se muestra el estante de la tienda del creador debajo del reproductor de video</string>
<string name="revanced_hide_creator_store_shelf_summary_on">La estantería de la tienda del creador debajo del reproductor de vídeo está oculta</string>
<string name="revanced_hide_creator_store_shelf_summary_off">La estantería de la tienda del creador debajo del reproductor de vídeo es visible</string>
<string name="revanced_hide_end_screen_store_banner_title">Ocultar banner de la tienda en la pantalla final</string>
<string name="revanced_hide_end_screen_store_banner_summary_on">El banner de la tienda de la pantalla final está oculto</string>
<string name="revanced_hide_end_screen_store_banner_summary_off">El banner de la tienda de la pantalla final es visible</string>
<string name="revanced_hide_end_screen_store_banner_summary_off">El banner de la tienda de la pantalla final es visible</string>
<string name="revanced_hide_fullscreen_ads_title">Ocultar anuncios a pantalla completa</string>
<string name="revanced_hide_fullscreen_ads_summary_on">"Los anuncios a pantalla completa están ocultos
@@ -421,7 +421,7 @@ Esta función solo está disponible para dispositivos antiguos"</string>
<string name="revanced_hide_shopping_links_summary_off">Se muestran los enlaces de compras en la descripción del video</string>
<string name="revanced_hide_view_products_banner_title">Ocultar el banner \"Ver productos\"</string>
<string name="revanced_hide_view_products_banner_summary_on">El banner \"Ver productos\" en la superposición de vídeo está oculto</string>
<string name="revanced_hide_view_products_banner_summary_off">El banner \"Ver productos\" en la superposición de vídeo es visible</string>
<string name="revanced_hide_view_products_banner_summary_off">El banner \"Ver productos\" en la superposición de vídeo es visible</string>
<string name="revanced_hide_web_search_results_title">Ocultar resultados de búsqueda web</string>
<string name="revanced_hide_web_search_results_summary_on">Los resultados de búsqueda web están ocultos</string>
<string name="revanced_hide_web_search_results_summary_off">Se muestran los resultados de la búsqueda web</string>
@@ -432,7 +432,7 @@ Esta función solo está disponible para dispositivos antiguos"</string>
<string name="revanced_hide_get_premium_summary_off">Se muestran las promociones de YouTube Premium en el reproductor de vídeo</string>
</patch>
<patch id="ad.video.videoAdsPatch">
<string name="revanced_hide_video_ads_title">Ocultar anuncios de video</string>
<string name="revanced_hide_video_ads_title">Ocultar anuncios de vídeo</string>
<string name="revanced_hide_video_ads_summary_on">Los anuncios de vídeo están ocultos</string>
<string name="revanced_hide_video_ads_summary_off">Los anuncios de vídeo se muestran</string>
</patch>
@@ -463,7 +463,7 @@ Esta función solo está disponible para dispositivos antiguos"</string>
<string name="revanced_disable_chapter_skip_double_tap_summary_off">El doble toque puede ocasionalmente activar un salto al capítulo siguiente/anterior</string>
</patch>
<patch id="interaction.downloads.downloadsResourcePatch">
<string name="revanced_external_downloader_screen_title">Descargas externa</string>
<string name="revanced_external_downloader_screen_title">Descargas externas</string>
<string name="revanced_external_downloader_screen_summary">Configuración para el uso de un descargador externo</string>
<string name="revanced_external_downloader_title">Mostrar botón externo de descarga</string>
<string name="revanced_external_downloader_summary_on">Se muestra el botón de descarga en el reproductor</string>
@@ -486,7 +486,7 @@ Verifica que el nombre del paquete sea correcto y que la aplicación esté insta
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
<string name="revanced_disable_precise_seeking_gesture_title">Desactivar gesto de búsqueda preciso</string>
<string name="revanced_disable_precise_seeking_gesture_summary_on">El gesto está desactivado</string>
<string name="revanced_disable_precise_seeking_gesture_summary_off">Gesto habilitado</string>
<string name="revanced_disable_precise_seeking_gesture_summary_off">Gesto activado</string>
</patch>
<patch id="interaction.seekbar.enableSeekbarTappingPatch">
<string name="revanced_seekbar_tapping_title">Habilitar tocar para buscar</string>
@@ -495,7 +495,7 @@ Verifica que el nombre del paquete sea correcto y que la aplicación esté insta
</patch>
<patch id="interaction.swipecontrols.swipeControlsResourcePatch">
<string name="revanced_swipe_brightness_title">Activar gesto de brillo</string>
<string name="revanced_swipe_brightness_summary_on">"El deslizamiento de brillo a pantalla completa está habilitado
<string name="revanced_swipe_brightness_summary_on">"El deslizamiento de brillo a pantalla completa está activado
Ajusta el brillo deslizando verticalmente en el lado izquierdo de la pantalla"</string>
<string name="revanced_swipe_brightness_summary_off">El deslizamiento de brillo a pantalla completa está desactivado</string>
@@ -584,11 +584,11 @@ Ajusta el volumen deslizando verticalmente en el lado derecho de la pantalla"</s
This button only shows on videos uploaded by the logged in user. -->
<string name="revanced_hide_hype_button_title">Ocultar Hype</string>
<string name="revanced_hide_hype_button_summary_on">El botón Hype está oculto</string>
<string name="revanced_hide_hype_button_summary_off">El botón de hype es visible</string>
<string name="revanced_hide_hype_button_summary_off">El botón de hype es visible</string>
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_promote_button_title">Ocultar pestaña \'Promocionar\'</string>
<string name="revanced_hide_promote_button_summary_on">El botón de Promocionar está oculto</string>
<string name="revanced_hide_promote_button_summary_off">El botón de Promocionar es visible</string>
<string name="revanced_hide_promote_button_summary_off">El botón de Promocionar es visible</string>
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_thanks_button_title">Ocultar Gracias</string>
<string name="revanced_hide_thanks_button_summary_on">El botón de gracias está oculto</string>
@@ -633,14 +633,14 @@ Ajusta el volumen deslizando verticalmente en el lado derecho de la pantalla"</s
<string name="revanced_switch_create_with_notifications_button_title">Cambiar botón Crear con el de Notificaciones</string>
<string name="revanced_switch_create_with_notifications_button_summary_on">"El botón Crear se cambia por el botón Notificaciones
Nota: Habilitar esto también ocultará forzosamente los anuncios de video"</string>
Nota: Habilitar esto también ocultará forzosamente los anuncios de vídeo"</string>
<string name="revanced_switch_create_with_notifications_button_summary_off">El botón Crear no se cambia con el botón de notificaciones</string>
<string name="revanced_switch_create_with_notifications_button_user_dialog_message">"Deshabilitar este ajuste también deshabilitará el bloqueo de anuncios de Shorts.
Si cambiar este ajuste no tiene efecto, intenta cambiar al modo incógnito."</string>
<string name="revanced_hide_navigation_button_labels_title">Ocultar etiquetas de navegación</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Las etiquetas están ocultas</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Las etiquetas están visibles</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Las etiquetas son visibles</string>
<string name="revanced_disable_translucent_status_bar_title">Desactivar la barra de estado translúcida</string>
<string name="revanced_disable_translucent_status_bar_summary_on">La barra de estado es opaca</string>
<string name="revanced_disable_translucent_status_bar_summary_off">La barra de estado es opaca o translúcida</string>
@@ -669,7 +669,7 @@ Si cambiar este ajuste no tiene efecto, intenta cambiar al modo incógnito."</st
<string name="revanced_hide_player_flyout_sleep_timer_summary_off">El menú de temporizador de sueño se muestra</string>
<!-- 'Loop video' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_loop_video_title">Ocultar video de bucle</string>
<string name="revanced_hide_player_flyout_loop_video_summary_on">El menú de video en bucle está oculto</string>
<string name="revanced_hide_player_flyout_loop_video_summary_on">El menú de vídeo en bucle está oculto</string>
<string name="revanced_hide_player_flyout_loop_video_summary_off">El menú de vídeo en bucle se muestra</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_ambient_mode_title">Ocultar Modo ambiente</string>
@@ -702,14 +702,14 @@ Si cambiar este ajuste no tiene efecto, intenta cambiar al modo incógnito."</st
<!-- '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">"El menú de la pista de audio está oculto.
Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de video\" a iOS TV"</string>
Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de vídeo\" a iOS TV"</string>
<!-- '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">Ocultar reloj en VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Ver en el menú VR está oculto</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Ver en el menú VR se muestra</string>
<string name="revanced_hide_player_flyout_video_quality_title">Ocultar menú de calidad de vídeo</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">El menú de calidad de video está oculto</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">El menú de calidad de video es visible</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">El menú de calidad de vídeo está oculto</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">El menú de calidad de vídeo es visible</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Ocultar pie de página del menú de calidad de vídeo</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Pie de menú de calidad de vídeo oculto</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">El pie del menú de calidad de vídeo se muestra</string>
@@ -745,7 +745,7 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<patch id="layout.hide.infocards.hideInfocardsResourcePatch">
<string name="revanced_hide_info_cards_title">Ocultar tarjetas de información</string>
<string name="revanced_hide_info_cards_summary_on">Las tarjetas de información están ocultas</string>
<string name="revanced_hide_info_cards_summary_off">Las tarjetas de información están visibles</string>
<string name="revanced_hide_info_cards_summary_off">Las tarjetas de información son visibles</string>
</patch>
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
<string name="revanced_disable_rolling_number_animations_title">Desactivar animaciones de número de rodamiento</string>
@@ -759,7 +759,7 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
<string name="revanced_hide_seekbar_thumbnail_title">Ocultar barra de búsqueda de miniaturas de vídeo</string>
<string name="revanced_hide_seekbar_thumbnail_summary_on">La barra de búsqueda de miniaturas de vídeo está oculta</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">La barra de búsqueda de miniaturas de vídeo es visible</string>
<string name="revanced_hide_seekbar_thumbnail_summary_off">La barra de búsqueda de miniaturas de vídeo es visible</string>
</patch>
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
<string name="revanced_shorts_player_screen_title">Reproductor de Shorts</string>
@@ -780,10 +780,10 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<string name="revanced_hide_shorts_history_summary_off">Mostrado en el historial de visualización</string>
<string name="revanced_hide_shorts_super_thanks_button_title">Ocultar el botón Comprar Súper Gracias</string>
<string name="revanced_hide_shorts_super_thanks_button_summary_on">El botón Comprar Super Thanks está oculto</string>
<string name="revanced_hide_shorts_super_thanks_button_summary_off">El botón Comprar Super Thanks es visible</string>
<string name="revanced_hide_shorts_super_thanks_button_summary_off">El botón Comprar Super Thanks es visible</string>
<string name="revanced_hide_shorts_effect_button_title">Ocultar botón de efecto</string>
<string name="revanced_hide_shorts_effect_button_summary_on">El botón de efecto está oculto</string>
<string name="revanced_hide_shorts_effect_button_summary_off">El botón de efecto es visible</string>
<string name="revanced_hide_shorts_effect_button_summary_off">El botón de efecto es visible</string>
<string name="revanced_hide_shorts_green_screen_button_title">Ocultar el botón Pantalla verde</string>
<string name="revanced_hide_shorts_green_screen_button_summary_on">El botón verde de pantalla está oculto</string>
<string name="revanced_hide_shorts_green_screen_button_summary_off">Se muestra el botón verde de pantalla</string>
@@ -829,7 +829,7 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<string name="revanced_hide_shorts_upcoming_button_summary_off">Se muestra el botón próximo</string>
<string name="revanced_hide_shorts_use_sound_button_title">Ocultar el botón Usar este sonido</string>
<string name="revanced_hide_shorts_use_sound_button_summary_on">El botón Usar este sonido está oculto</string>
<string name="revanced_hide_shorts_use_sound_button_summary_off">El botón Usar este sonido es visible</string>
<string name="revanced_hide_shorts_use_sound_button_summary_off">El botón Usar este sonido es visible</string>
<string name="revanced_hide_shorts_use_template_button_title">Ocultar botón Usar esta plantilla</string>
<string name="revanced_hide_shorts_use_template_button_summary_on">El botón Usar esta plantilla está oculto</string>
<string name="revanced_hide_shorts_use_template_button_summary_off">El botón Usar esta plantilla se muestra</string>
@@ -864,16 +864,16 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<string name="revanced_hide_shorts_channel_bar_summary_off">Barra de canales mostrada</string>
<string name="revanced_hide_shorts_video_title_title">Ocultar título de vídeo</string>
<string name="revanced_hide_shorts_video_title_summary_on">El título del vídeo está oculto</string>
<string name="revanced_hide_shorts_video_title_summary_off">El título del vídeo es visible</string>
<string name="revanced_hide_shorts_video_title_summary_off">El título del vídeo es visible</string>
<string name="revanced_hide_shorts_sound_metadata_label_title">Ocultar etiqueta de metadatos de sonido</string>
<string name="revanced_hide_shorts_sound_metadata_label_summary_on">La etiqueta de metadatos de sonido está oculta</string>
<string name="revanced_hide_shorts_sound_metadata_label_summary_off">La etiqueta de metadatos de sonido es visible</string>
<string name="revanced_hide_shorts_sound_metadata_label_summary_off">La etiqueta de metadatos de sonido es visible</string>
<string name="revanced_hide_shorts_full_video_link_label_title">Ocultar la etiqueta del enlace del video</string>
<string name="revanced_hide_shorts_full_video_link_label_summary_on">Etiqueta de enlace de vídeo oculto</string>
<string name="revanced_hide_shorts_full_video_link_label_summary_off">Etiqueta de enlace de vídeo mostrada</string>
<string name="revanced_hide_shorts_navigation_bar_title">Ocultar barra de navegación</string>
<string name="revanced_hide_shorts_navigation_bar_summary_on">La barra de navegación está oculta</string>
<string name="revanced_hide_shorts_navigation_bar_summary_off">La barra de navegación es visible</string>
<string name="revanced_hide_shorts_navigation_bar_summary_off">La barra de navegación es visible</string>
</patch>
<patch id="layout.hide.endscreensuggestion.hideEndScreenSuggestedVideoPatch">
<string name="revanced_end_screen_suggested_video_title">Ocultar el vídeo sugerido de la pantalla final</string>
@@ -886,7 +886,7 @@ Configuración → Reproducción → Reproducir el siguiente vídeo automáticam
<patch id="layout.hide.relatedvideooverlay.hideRelatedVideoOverlayPatch">
<string name="revanced_hide_related_videos_overlay_title">Ocultar la superposición de vídeos relacionados</string>
<string name="revanced_hide_related_videos_overlay_summary_on">La superposición de vídeos relacionados en pantalla completa está oculta</string>
<string name="revanced_hide_related_videos_overlay_summary_off">La superposición de vídeos relacionados en pantalla completa es visible</string>
<string name="revanced_hide_related_videos_overlay_summary_off">La superposición de vídeos relacionados en pantalla completa es visible</string>
</patch>
<patch id="layout.hide.time.hideTimestampPatch">
<string name="revanced_hide_timestamp_title">Ocultar fecha y hora de vídeo</string>
@@ -894,9 +894,9 @@ Configuración → Reproducción → Reproducir el siguiente vídeo automáticam
<string name="revanced_hide_timestamp_summary_off">Marca de tiempo mostrada</string>
</patch>
<patch id="layout.panels.popup.playerPopupPanelsPatch">
<string name="revanced_hide_player_popup_panels_title">Ocultar paneles emergentes del jugador</string>
<string name="revanced_hide_player_popup_panels_summary_on">Los paneles emergentes del jugador están ocultos</string>
<string name="revanced_hide_player_popup_panels_summary_off">Se muestran paneles emergentes del jugador</string>
<string name="revanced_hide_player_popup_panels_title">Ocultar paneles emergentes del reproductor</string>
<string name="revanced_hide_player_popup_panels_summary_on">Los paneles emergentes del reproductor están ocultos</string>
<string name="revanced_hide_player_popup_panels_summary_off">Se muestran paneles emergentes del reproductor</string>
</patch>
<patch id="layout.player.fullscreen.exitFullscreenPatch">
<string name="revanced_exit_fullscreen_title">Salir del modo de pantalla completa al final del vídeo</string>
@@ -908,10 +908,10 @@ Configuración → Reproducción → Reproducir el siguiente vídeo automáticam
<patch id="layout.player.fullscreen.openVideosFullscreen">
<string name="revanced_open_videos_fullscreen_portrait_title">Abrir vídeos en el retrato de pantalla completa</string>
<string name="revanced_open_videos_fullscreen_portrait_summary_on">Videos abiertos a pantalla completa</string>
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Los videos no se abren en pantalla completa</string>
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Los vídeos no se abren en pantalla completa</string>
</patch>
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
<string name="revanced_player_overlay_opacity_title">Opacidad de superposición del jugador</string>
<string name="revanced_player_overlay_opacity_title">Opacidad de superposición del reproductor</string>
<string name="revanced_player_overlay_opacity_summary">Valor de potencia entre 0-100, donde 0 es transparente</string>
<string name="revanced_player_overlay_opacity_invalid_toast">Opacidad del reproductor debe estar entre 0 y 100</string>
</patch>
@@ -967,7 +967,7 @@ Limitación: Es posible que los Dislikes no aparezcan en el modo de incógnito"<
<patch id="layout.searchbar.wideSearchbarPatch">
<string name="revanced_wide_searchbar_title">Habilitar barra de búsqueda ancha</string>
<string name="revanced_wide_searchbar_summary_on">Barra de búsqueda ancha habilitada</string>
<string name="revanced_wide_searchbar_summary_off">Barra de búsqueda ancha desactivada</string>
<string name="revanced_wide_searchbar_summary_off">La barra de búsqueda ancha está desactivada</string>
</patch>
<patch id="layout.seekbar.seekbarThumbnailsPatch">
<string name="revanced_seekbar_thumbnails_high_quality_title">Habilitar miniaturas de alta calidad</string>
@@ -984,7 +984,7 @@ Esta función funciona mejor con una calidad de vídeo de 720p o inferior y cuan
</patch>
<patch id="layout.sponsorblock.sponsorBlockResourcePatch">
<string name="revanced_sb_enable_sb">Activar SponsorBlock</string>
<string name="revanced_sb_enable_sb_sum">SponsorBlock es un sistema de colaboración abierta para omitir partes molestas de los videos de YouTube</string>
<string name="revanced_sb_enable_sb_sum">SponsorBlock es un sistema de colaboración abierta para omitir partes molestas de los vídeos de YouTube</string>
<string name="revanced_sb_appearance_category">Apariencia</string>
<string name="revanced_sb_enable_voting">Mostrar botón de voto</string>
<string name="revanced_sb_enable_voting_sum_on">Se muestra el botón de voto del segmento</string>
@@ -1038,7 +1038,7 @@ Esta función funciona mejor con una calidad de vídeo de 720p o inferior y cuan
<string name="revanced_sb_toast_on_connection_error_summary_off">Toast no se muestra si SponsorBlock no está disponible</string>
<string name="revanced_sb_general_skipcount">Habilitar rastreo del conteo de saltos</string>
<string name="revanced_sb_general_skipcount_sum_on">Permite que la tabla de clasificación de SponsorBlock sepa cuánto tiempo se ha ahorrado. Un mensaje se envía al tablero de clasificación cada vez que se omite un segmento</string>
<string name="revanced_sb_general_skipcount_sum_off">El rastreo del conteo de saltos no está habilitado</string>
<string name="revanced_sb_general_skipcount_sum_off">El rastreo del conteo de saltos no está activado</string>
<string name="revanced_sb_general_min_duration">Duración mínima del segmento</string>
<string name="revanced_sb_general_min_duration_sum">Los segmentos más cortos que este valor (en segundos) no se mostrarán o se omitirán</string>
<string name="revanced_sb_general_min_duration_invalid">Duración de tiempo no válida</string>
@@ -1357,7 +1357,7 @@ Habilitar esto puede solucionar las imágenes que faltan que están bloqueadas e
<string name="revanced_alt_thumbnail_options_entry_4">Sigue capturando</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow proporciona miniaturas de vídeos de YouTube obtenidas mediante crowdsourcing. Estas miniaturas suelen ser más relevantes que las que proporciona YouTube
Si está habilitado, las URL de los vídeos se enviarán al servidor de la API y no se envían otros datos. Si un vídeo no tiene miniaturas de DeArrow, se mostrarán las originales o las capturas fijas
Si está activado, las URL de los vídeos se enviarán al servidor de la API y no se envían otros datos. Si un vídeo no tiene miniaturas de DeArrow, se mostrarán las originales o las capturas fijas
Toca aquí para obtener más información sobre DeArrow"</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Mostrar un brindis si la API no está disponible</string>
@@ -1449,7 +1449,7 @@ Habilitar esto puede desbloquear calidades de vídeo más altas"</string>
<string name="revanced_force_original_audio_summary_on">Usar el idioma de audio original</string>
<string name="revanced_force_original_audio_summary_off">Utilizando audio predeterminado</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">Para usar esta función, cambia \"Suplantar transmisiones de video\" a iOS TV</string>
<string name="revanced_force_original_audio_not_available">Para usar esta función, cambia \"Suplantar transmisiones de vídeo\" a iOS TV</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1457,9 +1457,9 @@ Habilitar esto puede desbloquear calidades de vídeo más altas"</string>
<string name="revanced_remember_video_quality_last_selected_title">Recordar cambios de calidad de vídeo</string>
<string name="revanced_remember_video_quality_last_selected_summary_on">Los cambios de calidad se aplican a todos los vídeos</string>
<string name="revanced_remember_video_quality_last_selected_summary_off">Los cambios de calidad sólo se aplican al vídeo actual</string>
<string name="revanced_remember_video_quality_last_selected_toast_title">Mostrar notificación al cambiar la calidad de video</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_on">Se muestra una notificación cuando se cambia la calidad de video predeterminada</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_off">No se muestra una notificación cuando se cambia la calidad de video predeterminada</string>
<string name="revanced_remember_video_quality_last_selected_toast_title">Mostrar notificación al cambiar la calidad de vídeo</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_on">Se muestra una notificación cuando se cambia la calidad de vídeo predeterminada</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_off">No se muestra una notificación cuando se cambia la calidad de vídeo predeterminada</string>
<string name="revanced_video_quality_default_wifi_title">Calidad de vídeo predeterminada en la red Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">Calidad de vídeo predeterminada en la red móvil</string>
<string name="revanced_remember_shorts_quality_last_selected_title">Recordar cambios en la calidad de Shorts</string>
@@ -1478,14 +1478,14 @@ Habilitar esto puede desbloquear calidades de vídeo más altas"</string>
<string name="revanced_playback_speed_dialog_button_summary_off">El botón no se muestra</string>
</patch>
<patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Mostrar botón de calidad de video</string>
<string name="revanced_video_quality_dialog_button_title">Mostrar botón de calidad de vídeo</string>
<string name="revanced_video_quality_dialog_button_summary_on">Botón visible. Toca y mantén para restablecer la calidad a los valores predeterminados</string>
<string name="revanced_video_quality_dialog_button_summary_off">Botón no visible</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">Menú de velocidad de reproducción personalizada</string>
<string name="revanced_custom_speed_menu_summary_on">Menú de velocidad personalizado se muestra</string>
<string name="revanced_custom_speed_menu_summary_off">Menú de velocidad personalizado no se muestra</string>
<string name="revanced_custom_speed_menu_summary_on">El menú de velocidad personalizada se muestra</string>
<string name="revanced_custom_speed_menu_summary_off">El menú de velocidad personalizada no se muestra</string>
<string name="revanced_restore_old_speed_menu_title">Restaurar el menú de velocidad de reproducción antiguo</string>
<string name="revanced_restore_old_speed_menu_summary_on">Se muestra el menú de velocidad antiguo</string>
<string name="revanced_restore_old_speed_menu_summary_off">Se muestra el menú de velocidad moderno</string>
@@ -1520,7 +1520,7 @@ Habilitar esto puede desbloquear calidades de vídeo más altas"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
<string name="revanced_slide_to_seek_title">Habilitar diapositiva para buscar</string>
<string name="revanced_slide_to_seek_summary_on">Deslizar para buscar está activado</string>
<string name="revanced_slide_to_seek_summary_off">Slide to seek no está habilitado</string>
<string name="revanced_slide_to_seek_summary_off">Slide to seek no está activado</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Falsificación del stream de vídeo</string>
@@ -1533,21 +1533,21 @@ Es posible que la reproducción de vídeo no funcione"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Desactivar esta configuración puede causar problemas de reproducción de vídeo.</string>
<string name="revanced_spoof_video_streams_client_type_title">Cliente por defecto</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Forzar iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">El códec de video se fuerza a AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">El códec de video se determina automáticamente</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">El códec de vídeo se fuerza a AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">El códec de vídeo se determina automáticamente</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Habilitar esto puede mejorar la duración de la batería y solucionar el tartamudeo de la reproducción.
AVC tiene una resolución máxima de 1080p, el códec de audio Opus no está disponible y la reproducción de video utilizará más datos de Internet que VP9 o AV1."</string>
AVC tiene una resolución máxima de 1080p, el códec de audio Opus no está disponible y la reproducción de vídeo utilizará más datos de Internet que VP9 o AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">Efectos secundarios de la suplantación de iOS</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Es posible que las películas o los videos pagos no se reproduzcan
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Es posible que las películas o los vídeos pagos no se reproduzcan
• El volumen estable no está disponible
• Los videos terminan 1 segundo antes"</string>
• Los vídeos terminan 1 segundo antes"</string>
<string name="revanced_spoof_video_streams_about_android_title">Efectos secundarios de la suplantación de Android</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Falta el menú de la pista de audio
• El volumen estable no está disponible
• Forzar el audio original no está disponible"</string>
<string name="revanced_spoof_video_streams_about_no_av1">• No AV1 códec de vídeo</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Es posible que los videos infantiles no se reproduzcan cuando se cierra la sesión o se está en modo incógnito</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Es posible que los vídeos infantiles no se reproduzcan cuando se cierra la sesión o se está en modo incógnito</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Mostrar en Estadísticas para nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">El tipo de cliente se muestra en Estadísticas para nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">El cliente está oculto en Estadísticas para nerds</string>
@@ -1588,7 +1588,7 @@ AVC tiene una resolución máxima de 1080p, el códec de audio Opus no está dis
<patch id="debug.debugModePatch">
<!-- Twitch specific internal debug mode, and not the same as 'revanced_debug_title'. -->
<string name="revanced_twitch_debug_mode_title">Activar modo de depuración de Twitch</string>
<string name="revanced_twitch_debug_mode_summary_on">El modo de depuración de Twitch está habilitado (no recomendado)</string>
<string name="revanced_twitch_debug_mode_summary_on">El modo de depuración de Twitch está activado (no recomendado)</string>
<string name="revanced_twitch_debug_mode_summary_off">El modo de depuración de Twitch está desactivado</string>
</patch>
<patch id="misc.settings.settingsPatch">

View File

@@ -1078,7 +1078,7 @@ Id pengguna Anda seperti kata sandi dan jangan pernah dibagikan."</string>
<string name="revanced_sb_segments_hook_sum">Trailer yang dinarasikan untuk video mendatang, sapaan, dan perpisahan. Tidak termasuk bagian yang menambahkan konten tambahan</string>
<string name="revanced_sb_segments_preview">Pratinjau / Rekap</string>
<string name="revanced_sb_segments_preview_sum">Kumpulan klip yang menunjukkan apa yang akan datang atau apa yang terjadi di video atau di video lain dari sebuah seri, di mana semua informasi diulang di tempat lain</string>
<string name="revanced_sb_segments_filler">Penyimpangan / Lelucon</string>
<string name="revanced_sb_segments_filler">Singgungan / Lelucon</string>
<string name="revanced_sb_segments_filler_sum">Adegan atau lelucon sampingan yang tidak diperlukan untuk memahami konten utama video. Tidak termasuk bagian yang memberikan konteks atau detail latar belakang</string>
<string name="revanced_sb_segments_nomusic">Musik: Bagian Non-Musik</string>
<string name="revanced_sb_segments_nomusic_sum">Hanya untuk digunakan pada video musik. Bagian video musik tanpa musiknya, yang belum tercakup dalam kategori lain</string>
@@ -1092,11 +1092,11 @@ Id pengguna Anda seperti kata sandi dan jangan pernah dibagikan."</string>
<string name="revanced_sb_skip_button_intro_middle">Lewati jeda</string>
<string name="revanced_sb_skip_button_intro_end">Lewati jeda</string>
<string name="revanced_sb_skip_button_outro">Lewati outro</string>
<string name="revanced_sb_skip_button_hook">Lewati hook</string>
<string name="revanced_sb_skip_button_hook">Lewati pengantar</string>
<string name="revanced_sb_skip_button_preview_beginning">Lewati pratinjau</string>
<string name="revanced_sb_skip_button_preview_middle">Lewati pratinjau</string>
<string name="revanced_sb_skip_button_preview_end">Lewati rekap</string>
<string name="revanced_sb_skip_button_filler">Lewati penyimpangan</string>
<string name="revanced_sb_skip_button_filler">Lewati singgungan</string>
<string name="revanced_sb_skip_button_nomusic">Lewati non-musik</string>
<string name="revanced_sb_skip_button_unsubmitted">Lewati segmen</string>
<string name="revanced_sb_skipped_sponsor">Sponsor dilewati</string>
@@ -1107,11 +1107,11 @@ Id pengguna Anda seperti kata sandi dan jangan pernah dibagikan."</string>
<string name="revanced_sb_skipped_intro_middle">Jeda dilewati</string>
<string name="revanced_sb_skipped_intro_end">Jeda dilewati</string>
<string name="revanced_sb_skipped_outro">Outro dilewati</string>
<string name="revanced_sb_skipped_hook">Hook dilewati</string>
<string name="revanced_sb_skipped_hook">Sapaan dilewati</string>
<string name="revanced_sb_skipped_preview_beginning">Pratinjau dilewati</string>
<string name="revanced_sb_skipped_preview_middle">Pratinjau dilewati</string>
<string name="revanced_sb_skipped_preview_end">Rekap dilewati</string>
<string name="revanced_sb_skipped_filler">Penyimpangan dilewati</string>
<string name="revanced_sb_skipped_filler">Singgungan dilewati</string>
<string name="revanced_sb_skipped_nomusic">Melewati bagian non-musik</string>
<string name="revanced_sb_skipped_unsubmitted">Melewati segmen yang belum dikirim</string>
<string name="revanced_sb_skipped_multiple_segments">Beberapa segmen dilewati</string>

View File

@@ -1077,7 +1077,7 @@ Second \"item\" text"</string>
<string name="revanced_sb_segments_intro_sum">Интервал без фактического содержания. Может быть паузой, статическим кадром или повторяющейся анимацией. Не включает переходы, содержащие информацию</string>
<string name="revanced_sb_segments_outro">Конечные заставки / Титры</string>
<string name="revanced_sb_segments_outro_sum">Титры или время появления конечных заставок YouTube. Не для выводов с информацией</string>
<string name="revanced_sb_segments_hook">Вступление / Приветствия</string>
<string name="revanced_sb_segments_hook">Вступление / Приветствие</string>
<string name="revanced_sb_segments_hook_sum">Трейлеры с закадровым голосом для предстоящего видео, приветствия и прощания. Не включает разделы, добавляющие дополнительный контент</string>
<string name="revanced_sb_segments_preview">Предпросмотр / Пересказ</string>
<string name="revanced_sb_segments_preview_sum">Фрагменты, повторяющие текущее видео или предыдущие серии</string>
@@ -1095,11 +1095,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skip_button_intro_middle">Пропустить паузу</string>
<string name="revanced_sb_skip_button_intro_end">Пропустить паузу</string>
<string name="revanced_sb_skip_button_outro">Пропустить концовку</string>
<string name="revanced_sb_skip_button_hook">Пропустить завязку</string>
<string name="revanced_sb_skip_button_hook">Пропустить вступление</string>
<string name="revanced_sb_skip_button_preview_beginning">Пропустить предпросмотр</string>
<string name="revanced_sb_skip_button_preview_middle">Пропустить предпросмотр</string>
<string name="revanced_sb_skip_button_preview_end">Пропустить пересказ</string>
<string name="revanced_sb_skip_button_filler">Пропустить отступление</string>
<string name="revanced_sb_skip_button_filler">Пропустить отвлеченные темы</string>
<string name="revanced_sb_skip_button_nomusic">Пропустить сегмент без музыки</string>
<string name="revanced_sb_skip_button_unsubmitted">Пропустить сегмент</string>
<string name="revanced_sb_skipped_sponsor">Спонсорская реклама пропущена</string>
@@ -1110,11 +1110,11 @@ Second \"item\" text"</string>
<string name="revanced_sb_skipped_intro_middle">Пауза пропущена</string>
<string name="revanced_sb_skipped_intro_end">Пауза пропущена</string>
<string name="revanced_sb_skipped_outro">Концовка пропущена</string>
<string name="revanced_sb_skipped_hook">Завязка пропущена</string>
<string name="revanced_sb_skipped_hook">Вступление пропущено</string>
<string name="revanced_sb_skipped_preview_beginning">Предпросмотр пропущен</string>
<string name="revanced_sb_skipped_preview_middle">Предпросмотр пропущен</string>
<string name="revanced_sb_skipped_preview_end">Пересказ пропущен</string>
<string name="revanced_sb_skipped_filler">Отступление пропущено</string>
<string name="revanced_sb_skipped_filler">Отвлеченные темы пропущены</string>
<string name="revanced_sb_skipped_nomusic">Сегмент без музыки пропущен</string>
<string name="revanced_sb_skipped_unsubmitted">Неподтвержденный сегмент пропущен</string>
<string name="revanced_sb_skipped_multiple_segments">Несколько сегментов пропущены</string>

View File

@@ -125,14 +125,12 @@
<app id="youtube">
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string-array name="revanced_spoof_video_streams_client_type_entries">
<item>Android TV</item>
<item>Android VR</item>
<item>iOS TV</item>
<item>VisionOS</item>
</string-array>
<string-array name="revanced_spoof_video_streams_client_type_entry_values">
<item>ANDROID_UNPLUGGED</item>
<item>ANDROID_VR_NO_AUTH</item>
<item>IOS_UNPLUGGED</item>
<item>ANDROID_VR_1_61_48</item>
<item>VISIONOS</item>
</string-array>
</patch>
<patch id="interaction.swipecontrols.swipeControlsResourcePatch">

View File

@@ -765,7 +765,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'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio track menu is hidden
To show the Audio track menu, change \'Spoof video streams\' to iOS TV"</string>
Audio track menu is not available when \'Spoof video streams\' is enabled"</string>
<!-- '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_summary_on">Watch in VR menu is hidden</string>
@@ -1613,32 +1613,25 @@ Enabling this can unlock higher video qualities"</string>
<string name="revanced_spoof_video_streams_screen_title">Spoof video streams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoof the client video streams to prevent playback issues</string>
<string name="revanced_spoof_video_streams_title">Spoof video streams</string>
<string name="revanced_spoof_video_streams_summary_on">Video streams are spoofed</string>
<string name="revanced_spoof_video_streams_summary_on">"Video streams are spoofed
If you are a YouTube Premium user, this setting may not be required"</string>
<string name="revanced_spoof_video_streams_summary_off">"Video streams are not spoofed
Video playback may not work"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Turning off this setting may cause video playback issues.</string>
<string name="revanced_spoof_video_streams_client_type_title">Default client</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Force iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video codec is forced to AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video codec is determined automatically</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Enabling this might improve battery life and fix playback stuttering.
AVC has a maximum resolution of 1080p, Opus audio codec is not available, and video playback will use more internet data than VP9 or AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS spoofing side effects</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Movies or paid videos may not play
• Stable volume is not available
• Videos end 1 second early"</string>
<string name="revanced_spoof_video_streams_about_title">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
• Stable volume is not available
• Force original audio is not available"</string>
• Stable volume is not available"</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_kids_videos">• Kids videos may not play when logged out or in incognito mode</string>
<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 type is shown in Stats for nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Client is hidden in Stats for nerds</string>
<string name="revanced_spoof_video_streams_language_title">VR default audio stream language</string>
<string name="revanced_spoof_video_streams_language_title">Audio stream language</string>
</patch>
</app>
<app id="twitch">