refactor(YouTube - Video playback): Add support for Shorts..

- Add 'Speed dialog' setting to Shorts custom actions
- Add default quality settings and default playback speed settings for Shorts
- Remove deprecated settings - 'Reject software AV1 codec response', 'Enable Shorts default playback speed'
- Reorder video categories
This commit is contained in:
inotia00 2025-03-28 19:31:25 +09:00
parent 82ceb8aa76
commit bf9ba0b1ef
13 changed files with 435 additions and 274 deletions

View File

@ -296,6 +296,11 @@ public final class CustomActionsPatch {
true
)
),
SPEED_DIALOG(
Settings.SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG,
"yt_outline_play_arrow_half_circle_black_24",
() -> VideoUtils.showPlaybackSpeedDialog(contextRef.get())
),
REPEAT_STATE(
Settings.SHORTS_CUSTOM_ACTIONS_REPEAT_STATE,
"yt_outline_arrow_repeat_1_black_24",

View File

@ -1,17 +1,10 @@
package app.revanced.extension.youtube.patches.video;
import static app.revanced.extension.shared.utils.StringRef.str;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.Utils;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
public class AV1CodecPatch {
private static final int LITERAL_VALUE_AV01 = 1635135811;
private static final int LITERAL_VALUE_DOLBY_VISION = 1685485123;
private static final String VP9_CODEC = "video/x-vnd.on2.vp9";
private static long lastTimeResponse = 0;
/**
* Replace the SW AV01 codec to VP9 codec.
@ -22,32 +15,4 @@ public class AV1CodecPatch {
public static String replaceCodec(String original) {
return Settings.REPLACE_AV1_CODEC.get() ? VP9_CODEC : original;
}
/**
* Replace the SW AV01 codec request with a Dolby Vision codec request.
* This request is invalid, so it falls back to codecs other than AV01.
* <p>
* Limitation: Fallback process causes about 15-20 seconds of buffering.
*
* @param literalValue literal value of the codec
*/
public static int rejectResponse(int literalValue) {
if (!Settings.REJECT_AV1_CODEC.get())
return literalValue;
Logger.printDebug(() -> "Response: " + literalValue);
if (literalValue != LITERAL_VALUE_AV01)
return literalValue;
final long currentTime = System.currentTimeMillis();
// Ignore the invoke within 20 seconds.
if (currentTime - lastTimeResponse > 20000) {
lastTimeResponse = currentTime;
Utils.showToastShort(str("revanced_reject_av1_codec_toast"));
}
return LITERAL_VALUE_DOLBY_VISION;
}
}

View File

@ -3,39 +3,73 @@ package app.revanced.extension.youtube.patches.video;
import static app.revanced.extension.shared.utils.StringRef.str;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.BooleanUtils;
import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.shared.settings.FloatSetting;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.Utils;
import app.revanced.extension.youtube.patches.utils.PatchStatus;
import app.revanced.extension.youtube.patches.video.requests.MusicRequest;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.ShortsPlayerState;
import app.revanced.extension.youtube.shared.VideoInformation;
import app.revanced.extension.youtube.whitelist.Whitelist;
@SuppressWarnings("unused")
public class PlaybackSpeedPatch {
private static final FloatSetting DEFAULT_PLAYBACK_SPEED =
Settings.DEFAULT_PLAYBACK_SPEED;
private static final FloatSetting DEFAULT_PLAYBACK_SPEED_SHORTS =
Settings.DEFAULT_PLAYBACK_SPEED_SHORTS;
private static final boolean DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC =
Settings.DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC.get();
private static final long TOAST_DELAY_MILLISECONDS = 750;
private static long lastTimeSpeedChanged;
private static float lastSelectedPlaybackSpeed = 1.0f;
private static volatile String channelId = "";
private static volatile String videoId = "";
private static boolean isLiveStream;
private static volatile String channelIdShorts = "";
private static volatile String videoIdShorts = "";
private static boolean isLiveStreamShorts;
/**
* Injection point.
*/
public static void newVideoStarted(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
isLiveStream = newlyLoadedLiveStreamValue;
if (isShorts()) {
channelIdShorts = newlyLoadedChannelId;
videoIdShorts = newlyLoadedVideoId;
isLiveStreamShorts = newlyLoadedLiveStreamValue;
Logger.printDebug(() -> "newVideoStarted: " + newlyLoadedVideoId);
} else {
channelId = newlyLoadedChannelId;
videoId = newlyLoadedVideoId;
isLiveStream = newlyLoadedLiveStreamValue;
final float defaultPlaybackSpeed = getDefaultPlaybackSpeed(newlyLoadedChannelId, newlyLoadedVideoId);
Logger.printDebug(() -> "overridePlaybackSpeed: " + defaultPlaybackSpeed);
Logger.printDebug(() -> "newShortsVideoStarted: " + newlyLoadedVideoId);
}
}
VideoInformation.overridePlaybackSpeed(defaultPlaybackSpeed);
/**
* Injection point.
*/
public static void newShortsVideoStarted(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
channelIdShorts = newlyLoadedChannelId;
videoIdShorts = newlyLoadedVideoId;
isLiveStreamShorts = newlyLoadedLiveStreamValue;
Logger.printInfo(() -> "newShortsVideoStarted: " + newlyLoadedVideoId);
}
/**
@ -65,17 +99,34 @@ public class PlaybackSpeedPatch {
/**
* Injection point.
*/
public static float getPlaybackSpeedInShorts(final float playbackSpeed) {
if (VideoInformation.lastPlayerResponseIsShort() &&
Settings.ENABLE_DEFAULT_PLAYBACK_SPEED_SHORTS.get()
) {
float defaultPlaybackSpeed = getDefaultPlaybackSpeed(VideoInformation.getChannelId(), null);
Logger.printDebug(() -> "overridePlaybackSpeed in Shorts: " + defaultPlaybackSpeed);
public static float getPlaybackSpeed(float playbackSpeed) {
boolean isShorts = isShorts();
String currentChannelId = isShorts ? channelIdShorts : channelId;
String currentVideoId = isShorts ? videoIdShorts : videoId;
boolean currentVideoIsLiveStream = isShorts ? isLiveStreamShorts : isLiveStream;
boolean currentVideoIsWhitelisted = Whitelist.isChannelWhitelistedPlaybackSpeed(currentChannelId);
boolean currentVideoIsMusic = !isShorts && isMusic();
return defaultPlaybackSpeed;
if (currentVideoIsLiveStream || currentVideoIsWhitelisted || currentVideoIsMusic) {
Logger.printDebug(() -> "changing playback speed to: 1.0");
VideoInformation.setPlaybackSpeed(1.0f);
return 1.0f;
}
return playbackSpeed;
float defaultPlaybackSpeed = isShorts ? DEFAULT_PLAYBACK_SPEED_SHORTS.get() : DEFAULT_PLAYBACK_SPEED.get();
if (defaultPlaybackSpeed < 0) {
float finalPlaybackSpeed = isShorts ? playbackSpeed : lastSelectedPlaybackSpeed;
VideoInformation.overridePlaybackSpeed(finalPlaybackSpeed);
Logger.printDebug(() -> "changing playback speed to: " + finalPlaybackSpeed);
return finalPlaybackSpeed;
} else {
if (isShorts) {
VideoInformation.setPlaybackSpeed(defaultPlaybackSpeed);
}
Logger.printDebug(() -> "changing playback speed to: " + defaultPlaybackSpeed);
return defaultPlaybackSpeed;
}
}
/**
@ -86,8 +137,19 @@ public class PlaybackSpeedPatch {
*/
public static void userSelectedPlaybackSpeed(float playbackSpeed) {
try {
if (PatchStatus.RememberPlaybackSpeed() &&
Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get()) {
boolean isShorts = isShorts();
if (PatchStatus.RememberPlaybackSpeed()) {
BooleanSetting rememberPlaybackSpeedLastSelectedSetting = isShorts
? Settings.REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED
: Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED;
FloatSetting playbackSpeedSetting = isShorts
? DEFAULT_PLAYBACK_SPEED_SHORTS
: DEFAULT_PLAYBACK_SPEED;
BooleanSetting showToastSetting = isShorts
? Settings.REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED_TOAST
: Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST;
if (rememberPlaybackSpeedLastSelectedSetting.get()) {
// With the 0.05x menu, if the speed is set by integrations to higher than 2.0x
// then the menu will allow increasing without bounds but the max speed is
// still capped to under 8.0x.
@ -104,33 +166,32 @@ public class PlaybackSpeedPatch {
// The user made additional speed adjustments and this call is outdated.
return;
}
if (Settings.DEFAULT_PLAYBACK_SPEED.get() == finalPlaybackSpeed) {
if (playbackSpeedSetting.get() == finalPlaybackSpeed) {
// User changed to a different speed and immediately changed back.
// Or the user is going past 8.0x in the glitched out 0.05x menu.
return;
}
Settings.DEFAULT_PLAYBACK_SPEED.save(finalPlaybackSpeed);
playbackSpeedSetting.save(finalPlaybackSpeed);
if (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST.get()) {
return;
if (showToastSetting.get()) {
Utils.showToastShort(str(isShorts ? "revanced_remember_playback_speed_toast_shorts" : "revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x")));
}
Utils.showToastShort(str("revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x")));
}, TOAST_DELAY_MILLISECONDS);
}
} else if (!isShorts){
lastSelectedPlaybackSpeed = playbackSpeed;
}
} catch (Exception ex) {
Logger.printException(() -> "userSelectedPlaybackSpeed failure", ex);
}
}
private static float getDefaultPlaybackSpeed(@NonNull String channelId, @Nullable String videoId) {
return (isLiveStream || Whitelist.isChannelWhitelistedPlaybackSpeed(channelId) || isMusic(videoId))
? 1.0f
: Settings.DEFAULT_PLAYBACK_SPEED.get();
private static boolean isShorts() {
return !ShortsPlayerState.getCurrent().isClosed();
}
private static boolean isMusic(@Nullable String videoId) {
if (DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC && videoId != null) {
private static boolean isMusic() {
if (DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC && !videoId.isEmpty()) {
try {
MusicRequest request = MusicRequest.getRequestForVideoId(videoId);
final boolean isMusic = request != null && BooleanUtils.toBoolean(request.getStream());

View File

@ -9,13 +9,16 @@ import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.Utils;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
import app.revanced.extension.youtube.shared.ShortsPlayerState;
import app.revanced.extension.youtube.shared.VideoInformation;
@SuppressWarnings("unused")
public class VideoQualityPatch {
private static final int DEFAULT_YOUTUBE_VIDEO_QUALITY = -2;
private static final IntegerSetting mobileQualitySetting = Settings.DEFAULT_VIDEO_QUALITY_MOBILE;
private static final IntegerSetting wifiQualitySetting = Settings.DEFAULT_VIDEO_QUALITY_WIFI;
private static final IntegerSetting shortsQualityMobile = Settings.DEFAULT_VIDEO_QUALITY_MOBILE_SHORTS;
private static final IntegerSetting shortsQualityWifi = Settings.DEFAULT_VIDEO_QUALITY_WIFI_SHORTS;
private static final IntegerSetting videoQualityMobile = Settings.DEFAULT_VIDEO_QUALITY_MOBILE;
private static final IntegerSetting videoQualityWifi = Settings.DEFAULT_VIDEO_QUALITY_WIFI;
@NonNull
public static String videoId = "";
@ -35,12 +38,11 @@ public class VideoQualityPatch {
public static void newVideoStarted(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
if (PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL)
return;
if (videoId.equals(newlyLoadedVideoId))
return;
if (PlayerType.getCurrent() != PlayerType.INLINE_MINIMAL &&
!videoId.equals(newlyLoadedVideoId)) {
videoId = newlyLoadedVideoId;
setVideoQuality(Settings.SKIP_PRELOADED_BUFFER.get() ? 250 : 750);
setVideoQuality(750);
}
}
/**
@ -53,14 +55,15 @@ public class VideoQualityPatch {
);
}
private static void setVideoQuality(final long delayMillis) {
final int defaultQuality = Utils.getNetworkType() == Utils.NetworkType.MOBILE
? mobileQualitySetting.get()
: wifiQualitySetting.get();
private static void setVideoQuality(long delayMillis) {
boolean isShorts = isShorts();
IntegerSetting defaultQualitySetting = Utils.getNetworkType() == Utils.NetworkType.MOBILE
? isShorts ? shortsQualityMobile : videoQualityMobile
: isShorts ? shortsQualityWifi : videoQualityWifi;
if (defaultQuality == DEFAULT_YOUTUBE_VIDEO_QUALITY)
return;
int defaultQuality = defaultQualitySetting.get();
if (defaultQuality != DEFAULT_YOUTUBE_VIDEO_QUALITY) {
Utils.runOnMainThreadDelayed(() -> {
final int qualityToUseFinal = VideoInformation.getAvailableVideoQuality(defaultQuality);
Logger.printDebug(() -> "Changing video quality to: " + qualityToUseFinal);
@ -68,27 +71,51 @@ public class VideoQualityPatch {
}, delayMillis
);
}
}
private static void userSelectedVideoQuality(final int defaultQuality) {
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get())
return;
if (defaultQuality == DEFAULT_YOUTUBE_VIDEO_QUALITY)
return;
if (defaultQuality != DEFAULT_YOUTUBE_VIDEO_QUALITY) {
boolean isShorts = isShorts();
final Utils.NetworkType networkType = Utils.getNetworkType();
String networkTypeMessage = networkType == Utils.NetworkType.MOBILE
? str("revanced_remember_video_quality_mobile")
: str("revanced_remember_video_quality_wifi");
switch (networkType) {
case NONE -> {
Utils.showToastShort(str("revanced_remember_video_quality_none"));
return;
if (isShorts) {
if (Settings.REMEMBER_VIDEO_QUALITY_SHORTS_LAST_SELECTED.get()) {
IntegerSetting defaultQualitySetting = networkType == Utils.NetworkType.MOBILE
? shortsQualityMobile
: shortsQualityWifi;
defaultQualitySetting.save(defaultQuality);
if (Settings.REMEMBER_VIDEO_QUALITY_SHORTS_LAST_SELECTED_TOAST.get()) {
Utils.showToastShort(str(
"revanced_remember_video_quality_toast_shorts",
networkTypeMessage, (defaultQuality + "p")
));
}
}
} else {
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get()) {
IntegerSetting defaultQualitySetting = networkType == Utils.NetworkType.MOBILE
? videoQualityMobile
: videoQualityWifi;
defaultQualitySetting.save(defaultQuality);
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) {
Utils.showToastShort(str(
"revanced_remember_video_quality_toast",
networkTypeMessage, (defaultQuality + "p")
));
}
}
}
}
case MOBILE -> mobileQualitySetting.save(defaultQuality);
default -> wifiQualitySetting.save(defaultQuality);
}
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get())
return;
Utils.showToastShort(str("revanced_remember_video_quality_" + networkType.getName(), defaultQuality + "p"));
private static boolean isShorts() {
return !ShortsPlayerState.getCurrent().isClosed();
}
}

View File

@ -498,12 +498,13 @@ public class Settings extends BaseSettings {
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL = new BooleanSetting("revanced_shorts_custom_actions_copy_video_url", FALSE, true);
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_shorts_custom_actions_external_downloader", FALSE, true);
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO = new BooleanSetting("revanced_shorts_custom_actions_open_video", FALSE, true);
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG = new BooleanSetting("revanced_shorts_custom_actions_speed_dialog", FALSE, true);
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_REPEAT_STATE = new BooleanSetting("revanced_shorts_custom_actions_repeat_state", FALSE, true);
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU = new BooleanSetting("revanced_enable_shorts_custom_actions_flyout_menu", FALSE, true,
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR = new BooleanSetting("revanced_enable_shorts_custom_actions_toolbar", FALSE, true,
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
// Experimental Flags
public static final BooleanSetting ENABLE_TIME_STAMP = new BooleanSetting("revanced_enable_shorts_time_stamp", FALSE, true);
@ -550,30 +551,38 @@ public class Settings extends BaseSettings {
public static final FloatSetting SWIPE_BRIGHTNESS_VALUE = new FloatSetting("revanced_swipe_brightness_value", -1.0f, false, false);
// PreferenceScreen: Video
public static final FloatSetting DEFAULT_PLAYBACK_SPEED = new FloatSetting("revanced_default_playback_speed", -2.0f);
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_MOBILE = new IntegerSetting("revanced_default_video_quality_mobile", -2);
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_WIFI = new IntegerSetting("revanced_default_video_quality_wifi", -2);
// PreferenceScreen: Video - Codec
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE, true);
public static final BooleanSetting DISABLE_VP9_CODEC = new BooleanSetting("revanced_disable_vp9_codec", FALSE, true);
public static final BooleanSetting REPLACE_AV1_CODEC = new BooleanSetting("revanced_replace_av1_codec", FALSE, true);
// PreferenceScreen: Video - Playback speed
public static final FloatSetting DEFAULT_PLAYBACK_SPEED = new FloatSetting("revanced_default_playback_speed", -2.0f);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", TRUE);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED));
public static final FloatSetting DEFAULT_PLAYBACK_SPEED_SHORTS = new FloatSetting("revanced_default_playback_speed_shorts", -2.0f);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_shorts_last_selected", TRUE);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_shorts_last_selected_toast", TRUE, parent(REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED));
public static final BooleanSetting ENABLE_CUSTOM_PLAYBACK_SPEED = new BooleanSetting("revanced_enable_custom_playback_speed", FALSE, true);
public static final BooleanSetting CUSTOM_PLAYBACK_SPEED_MENU_TYPE = new BooleanSetting("revanced_custom_playback_speed_menu_type", FALSE, parent(ENABLE_CUSTOM_PLAYBACK_SPEED));
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", "0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.25\n2.5", true, parent(ENABLE_CUSTOM_PLAYBACK_SPEED));
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", TRUE);
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED));
// PreferenceScreen: Video - Video quality
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_MOBILE = new IntegerSetting("revanced_default_video_quality_mobile", -2);
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_WIFI = new IntegerSetting("revanced_default_video_quality_wifi", -2);
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", TRUE);
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_video_quality_last_selected_toast", TRUE, parent(REMEMBER_VIDEO_QUALITY_LAST_SELECTED));
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_MOBILE_SHORTS = new IntegerSetting("revanced_default_video_quality_mobile_shorts", -2, true);
public static final IntegerSetting DEFAULT_VIDEO_QUALITY_WIFI_SHORTS = new IntegerSetting("revanced_default_video_quality_wifi_shorts", -2, true);
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_SHORTS_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_shorts_last_selected", TRUE);
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_SHORTS_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_video_quality_shorts_last_selected_toast", TRUE, parent(REMEMBER_VIDEO_QUALITY_SHORTS_LAST_SELECTED));
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE, true);
// Experimental Flags
public static final BooleanSetting DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC = new BooleanSetting("revanced_disable_default_playback_speed_music", FALSE, true);
public static final BooleanSetting DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC_TYPE = new BooleanSetting("revanced_disable_default_playback_speed_music_type", FALSE, true, parent(DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC));
public static final BooleanSetting ENABLE_DEFAULT_PLAYBACK_SPEED_SHORTS = new BooleanSetting("revanced_enable_default_playback_speed_shorts", FALSE);
public static final BooleanSetting SKIP_PRELOADED_BUFFER = new BooleanSetting("revanced_skip_preloaded_buffer", FALSE, true, "revanced_skip_preloaded_buffer_user_dialog_message");
public static final BooleanSetting SKIP_PRELOADED_BUFFER_TOAST = new BooleanSetting("revanced_skip_preloaded_buffer_toast", TRUE);
public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true);
public static final BooleanSetting DISABLE_VP9_CODEC = new BooleanSetting("revanced_disable_vp9_codec", FALSE, true);
public static final BooleanSetting REPLACE_AV1_CODEC = new BooleanSetting("revanced_replace_av1_codec", FALSE, true);
public static final BooleanSetting REJECT_AV1_CODEC = new BooleanSetting("revanced_reject_av1_codec", FALSE, true);
public static final BooleanSetting DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC = new BooleanSetting("revanced_disable_default_playback_speed_music", FALSE, true);
public static final BooleanSetting DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC_TYPE = new BooleanSetting("revanced_disable_default_playback_speed_music_type", FALSE, true, parent(DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC));
// PreferenceScreen: Miscellaneous
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);

View File

@ -10,6 +10,7 @@ import static app.revanced.extension.shared.utils.Utils.getChildView;
import static app.revanced.extension.shared.utils.Utils.isSDKAbove;
import static app.revanced.extension.shared.utils.Utils.showToastShort;
import static app.revanced.extension.youtube.settings.Settings.DEFAULT_PLAYBACK_SPEED;
import static app.revanced.extension.youtube.settings.Settings.DEFAULT_PLAYBACK_SPEED_SHORTS;
import static app.revanced.extension.youtube.settings.Settings.HIDE_PREVIEW_COMMENT;
import static app.revanced.extension.youtube.settings.Settings.HIDE_PREVIEW_COMMENT_TYPE;
@ -119,7 +120,7 @@ public class ReVancedPreferenceFragment extends PreferenceFragment {
} else {
Setting.privateSetValueFromString(setting, listPreference.getValue());
}
if (setting.equals(DEFAULT_PLAYBACK_SPEED)) {
if (setting.equals(DEFAULT_PLAYBACK_SPEED) || setting.equals(DEFAULT_PLAYBACK_SPEED_SHORTS)) {
listPreference.setEntries(CustomPlaybackSpeedPatch.getEntries());
listPreference.setEntryValues(CustomPlaybackSpeedPatch.getEntryValues());
}
@ -310,7 +311,7 @@ public class ReVancedPreferenceFragment extends PreferenceFragment {
} else if (preference instanceof EditTextPreference editTextPreference) {
editTextPreference.setText(setting.get().toString());
} else if (preference instanceof ListPreference listPreference) {
if (setting.equals(DEFAULT_PLAYBACK_SPEED)) {
if (setting.equals(DEFAULT_PLAYBACK_SPEED) || setting.equals(DEFAULT_PLAYBACK_SPEED_SHORTS)) {
listPreference.setEntries(CustomPlaybackSpeedPatch.getEntries());
listPreference.setEntryValues(CustomPlaybackSpeedPatch.getEntryValues());
}

View File

@ -46,6 +46,7 @@ public class ReVancedSettingsPreference extends ReVancedPreferenceFragment {
NavigationPreferenceLinks();
RYDPreferenceLinks();
SeekBarPreferenceLinks();
ShortsPreferenceLinks();
SpeedOverlayPreferenceLinks();
QuickActionsPreferenceLinks();
TabletLayoutLinks();
@ -186,6 +187,19 @@ public class ReVancedSettingsPreference extends ReVancedPreferenceFragment {
);
}
/**
* Enable/Disable Preference related to Shorts settings
*/
private static void ShortsPreferenceLinks() {
if (!PatchStatus.RememberPlaybackSpeed()) {
enableDisablePreferences(
true,
Settings.SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG
);
Settings.SHORTS_CUSTOM_ACTIONS_SPEED_DIALOG.save(false);
}
}
/**
* Enable/Disable Preference related to Speed overlay settings
*/

View File

@ -202,6 +202,7 @@ public class VideoUtils extends IntentUtils {
new AlertDialog.Builder(context)
.setSingleChoiceItems(playbackSpeedEntries, index, (mDialog, mIndex) -> {
final float selectedPlaybackSpeed = Float.parseFloat(playbackSpeedEntryValues[mIndex] + "f");
VideoInformation.setPlaybackSpeed(selectedPlaybackSpeed);
VideoInformation.overridePlaybackSpeed(selectedPlaybackSpeed);
userSelectedPlaybackSpeed(selectedPlaybackSpeed);
mDialog.dismiss();

View File

@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
@ -26,6 +25,7 @@ import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHoo
import app.revanced.patches.youtube.video.videoid.hookPlayerResponseVideoId
import app.revanced.patches.youtube.video.videoid.hookVideoId
import app.revanced.patches.youtube.video.videoid.videoIdPatch
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.addStaticFieldToExtension
import app.revanced.util.cloneMutable
import app.revanced.util.findMethodOrThrow
@ -94,6 +94,8 @@ private var mdxConstructorInsertIndex = -1
private lateinit var videoTimeConstructorMethod: MutableMethod
private var videoTimeConstructorInsertIndex = 2
private lateinit var setPlaybackSpeedMethodReference: MethodReference
// Used by other patches.
internal lateinit var speedSelectionInsertMethod: MutableMethod
internal lateinit var videoEndMethod: MutableMethod
@ -396,12 +398,13 @@ val videoInformationPatch = bytecodePatch(
Opcode.IGET_OBJECT
)
val setPlaybackSpeedContainerClassFieldReference =
getInstruction<ReferenceInstruction>(setPlaybackSpeedContainerClassFieldIndex).reference.toString()
getInstruction<ReferenceInstruction>(setPlaybackSpeedContainerClassFieldIndex).reference
val setPlaybackSpeedClassFieldReference =
getInstruction<ReferenceInstruction>(speedSelectionValueInstructionIndex + 1).reference.toString()
val setPlaybackSpeedMethodReference =
getInstruction<ReferenceInstruction>(speedSelectionValueInstructionIndex + 2).reference.toString()
getInstruction<ReferenceInstruction>(speedSelectionValueInstructionIndex + 1).reference
setPlaybackSpeedMethodReference =
getInstruction<ReferenceInstruction>(speedSelectionValueInstructionIndex + 2).reference as MethodReference
// add override playback speed method
it.classDef.methods.add(
@ -450,28 +453,81 @@ val videoInformationPatch = bytecodePatch(
}
}
playbackSpeedClassFingerprint.matchOrThrow().let { result ->
result.method.apply {
val index = result.patternMatch!!.endIndex
videoIdFingerprintShorts.matchOrThrow().let {
it.method.apply {
val shortsPlaybackSpeedClassField = it.classDef.fields.find { field ->
field.type == setPlaybackSpeedMethodReference.definingClass
} ?: throw PatchException("Failed to find hook field")
val smaliInstructions =
"""
if-eqz v0, :ignore
invoke-virtual {v0, p0}, $definingClass->overridePlaybackSpeed(F)V
:ignore
return-void
"""
addStaticFieldToExtension(
EXTENSION_CLASS_DESCRIPTOR,
"overridePlaybackSpeed",
"playbackSpeedShortsClass",
definingClass,
smaliInstructions
)
// add override playback speed method
it.classDef.methods.add(
ImmutableMethod(
definingClass,
"overridePlaybackSpeed",
listOf(ImmutableMethodParameter("F", annotations, null)),
"V",
AccessFlags.PUBLIC or AccessFlags.PUBLIC,
annotations,
null,
ImmutableMethodImplementation(
3, """
# Check if the playback speed is not auto (-2.0f)
const/4 v0, 0x0
cmpg-float v0, v2, v0
if-lez v0, :ignore
# Get the container class field.
iget-object v0, v1, $shortsPlaybackSpeedClassField
# For some reason, in YouTube 19.44.39 this value is sometimes null.
if-eqz v0, :ignore
# Invoke setPlaybackSpeed on that class.
invoke-virtual {v0, v2}, $setPlaybackSpeedMethodReference
:ignore
return-void
""".toInstructions(), null, null
)
).toMutable()
)
}
}
playbackSpeedClassFingerprint.methodOrThrow().apply {
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
val register = getInstruction<OneRegisterInstruction>(index).registerA
val playbackSpeedClass = this.returnType
// set playback speed class
replaceInstruction(
addInstructionsAtControlFlowLabel(
index,
"sput-object v$register, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedClass:$playbackSpeedClass"
)
addInstruction(
index + 1,
"return-object v$register"
)
val smaliInstructions =
"""
if-eqz v0, :ignore
invoke-virtual {v0, p0}, $playbackSpeedClass->overridePlaybackSpeed(F)V
:ignore
return-void
:ignore
nop
"""
addStaticFieldToExtension(
@ -483,7 +539,6 @@ val videoInformationPatch = bytecodePatch(
false
)
}
}
/**
* Hook current video quality

View File

@ -20,29 +20,6 @@ internal val av1CodecFingerprint = legacyFingerprint(
}
)
internal val byteBufferArrayFingerprint = legacyFingerprint(
name = "byteBufferArrayFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "I",
parameters = emptyList(),
opcodes = listOf(
Opcode.SHL_INT_LIT8,
Opcode.SHL_INT_LIT8,
Opcode.OR_INT_2ADDR,
Opcode.SHL_INT_LIT8,
Opcode.OR_INT_2ADDR,
Opcode.OR_INT_2ADDR,
Opcode.RETURN
)
)
internal val byteBufferArrayParentFingerprint = legacyFingerprint(
name = "byteBufferArrayParentFingerprint",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "C",
parameters = listOf("Ljava/nio/charset/Charset;", "[C")
)
internal val deviceDimensionsModelToStringFingerprint = legacyFingerprint(
name = "deviceDimensionsModelToStringFingerprint",
returnType = "L",
@ -77,17 +54,26 @@ internal val playbackSpeedChangedFromRecyclerViewFingerprint = legacyFingerprint
}
)
internal val playbackSpeedInitializeFingerprint = legacyFingerprint(
name = "playbackSpeedInitializeFingerprint",
returnType = "F",
accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC,
internal val loadVideoParamsFingerprint = legacyFingerprint(
name = "loadVideoParamsFingerprint",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET,
Opcode.RETURN
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IPUT,
Opcode.INVOKE_INTERFACE,
)
)
internal val loadVideoParamsParentFingerprint = legacyFingerprint(
name = "loadVideoParamsParentFingerprint",
returnType = "Z",
parameters = listOf("J"),
strings = listOf("LoadVideoParams.playerListener = null")
)
internal val qualityChangedFromRecyclerViewFingerprint = legacyFingerprint(
name = "qualityChangedFromRecyclerViewFingerprint",
returnType = "L",

View File

@ -24,8 +24,8 @@ import app.revanced.patches.youtube.utils.recyclerview.recyclerViewTreeObserverP
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
import app.revanced.patches.youtube.utils.settings.settingsPatch
import app.revanced.patches.youtube.utils.videoEndFingerprint
import app.revanced.patches.youtube.video.information.hookBackgroundPlayVideoInformation
import app.revanced.patches.youtube.video.information.hookShortsVideoInformation
import app.revanced.patches.youtube.video.information.hookVideoInformation
import app.revanced.patches.youtube.video.information.onCreateHook
import app.revanced.patches.youtube.video.information.speedSelectionInsertMethod
@ -44,6 +44,7 @@ import app.revanced.util.indexOfFirstStringInstructionOrThrow
import app.revanced.util.updatePatchStatus
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@ -158,21 +159,30 @@ val videoPlaybackPatch = bytecodePatch(
}
}
playbackSpeedInitializeFingerprint.matchOrThrow(videoEndFingerprint).let {
loadVideoParamsFingerprint.matchOrThrow(loadVideoParamsParentFingerprint).let {
it.method.apply {
val insertIndex = it.patternMatch!!.endIndex
val targetIndex = it.patternMatch!!.endIndex
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference as MethodReference
findMethodOrThrow(definingClass) {
name == targetReference.name
}.apply {
val insertIndex = implementation!!.instructions.lastIndex
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->getPlaybackSpeedInShorts(F)F
invoke-static {v$insertRegister}, $EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->getPlaybackSpeed(F)F
move-result v$insertRegister
"""
)
}
}
}
hookBackgroundPlayVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
hookShortsVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newShortsVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
hookVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
hookPlayerResponseVideoId("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->fetchMusicRequest(Ljava/lang/String;Z)V")
updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
@ -294,25 +304,6 @@ val videoPlaybackPatch = bytecodePatch(
settingArray += "SETTINGS: REPLACE_AV1_CODEC"
}
// reject av1 codec response
byteBufferArrayFingerprint.matchOrThrow(byteBufferArrayParentFingerprint).let {
it.method.apply {
val insertIndex = it.patternMatch!!.endIndex
val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $EXTENSION_AV1_CODEC_CLASS_DESCRIPTOR->rejectResponse(I)I
move-result v$insertRegister
"""
)
}
}
// endregion
// region patch for disable VP9 codec
vp9CapabilityFingerprint.methodOrThrow().apply {

View File

@ -1646,6 +1646,10 @@ Press and hold the More button to show the Custom actions dialog."</string>
<string name="revanced_shorts_custom_actions_open_video_title">Show open video menu</string>
<string name="revanced_shorts_custom_actions_open_video_summary_on">Open video menu is shown.</string>
<string name="revanced_shorts_custom_actions_open_video_summary_off">Open video menu is hidden.</string>
<string name="revanced_shorts_custom_actions_speed_dialog_label">Speed dialog</string>
<string name="revanced_shorts_custom_actions_speed_dialog_title">Show speed dialog menu</string>
<string name="revanced_shorts_custom_actions_speed_dialog_summary_on">Speed dialog menu is shown.</string>
<string name="revanced_shorts_custom_actions_speed_dialog_summary_off">Speed dialog menu is hidden.</string>
<string name="revanced_shorts_custom_actions_repeat_state_label">Repeat state</string>
<string name="revanced_shorts_custom_actions_repeat_state_title">Show repeat state menu</string>
<string name="revanced_shorts_custom_actions_repeat_state_summary_on">Repeat state menu is shown.</string>
@ -1763,12 +1767,45 @@ No margins on top and bottom of player."</string>
<!-- PreferenceScreen: Video -->
<string name="revanced_preference_screen_video_title">Video</string>
<string name="revanced_default_playback_speed_title">Default playback speed</string>
<string name="revanced_default_video_quality_mobile_title">Default video quality on mobile network</string>
<string name="revanced_default_video_quality_wifi_title">Default video quality on Wi-Fi network</string>
<!-- PreferenceScreen: Video, PreferenceCategory: Codec -->
<string name="revanced_preference_category_codec">Codec</string>
<string name="revanced_disable_hdr_video_title">Disable HDR video</string>
<string name="revanced_disable_hdr_video_summary_on">HDR video is disabled.</string>
<string name="revanced_disable_hdr_video_summary_off">HDR video is enabled.</string>
<string name="revanced_disable_vp9_codec_title">Disable VP9 codec</string>
<string name="revanced_disable_vp9_codec_summary_on">"VP9 codec is disabled.
Info:
• Maximum resolution is 1080p.
• Video playback will use more internet data than VP9.
• VP9 codec is still used for HDR video."</string>
<string name="revanced_disable_vp9_codec_summary_off">VP9 codec is enabled.</string>
<string name="revanced_replace_av1_codec_title">Replace software AV1 codec</string>
<string name="revanced_replace_av1_codec_summary">Replaces the software AV1 codec with the VP9 codec.</string>
<!-- PreferenceScreen: Video, PreferenceCategory: Playback speed -->
<string name="revanced_preference_category_playback_speed">Playback speed</string>
<string name="revanced_default_playback_speed_title">Default playback speed</string>
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
<string name="revanced_remember_playback_speed_last_selected_summary_on">Playback speed changes apply to all videos.</string>
<string name="revanced_remember_playback_speed_last_selected_summary_off">Playback speed changes only apply to the current video.</string>
<string name="revanced_remember_playback_speed_last_selected_toast_title">Show a toast</string>
<string name="revanced_remember_playback_speed_last_selected_toast_summary_on">A toast will be shown when changing the default playback speed.</string>
<string name="revanced_remember_playback_speed_last_selected_toast_summary_off">A toast will not be shown when changing the default playback speed.</string>
<string name="revanced_default_playback_speed_shorts_title">Default playback speed on Shorts</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_title">Remember playback speed changes on Shorts</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_summary_on">"Playback speed changes apply to all Shorts.
Info:
• The only way to change the playback speed in the Shorts player is to use the 'Speed dialog' in 'Custom actions'.
• If you didn't include the 'Shorts components' patch, this wouldn't be available."</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_summary_off">Playback speed changes only apply to the current Short.</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_toast_title">Show a toast</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_toast_summary_on">A toast will be shown when changing the default playback speed on Shorts.</string>
<string name="revanced_remember_playback_speed_shorts_last_selected_toast_summary_off">A toast will not be shown when changing the default playback speed on Shorts.</string>
<string name="revanced_remember_playback_speed_toast">Changed default playback speed to: %s.</string>
<string name="revanced_remember_playback_speed_toast_shorts">Changed default Shorts playback speed to: %s.</string>
<string name="revanced_enable_custom_playback_speed_title">Enable custom playback speed</string>
<string name="revanced_enable_custom_playback_speed_summary_on">Custom playback speed is enabled.</string>
<string name="revanced_enable_custom_playback_speed_summary_off">Custom playback speed is disabled.</string>
@ -1777,30 +1814,34 @@ No margins on top and bottom of player."</string>
<string name="revanced_custom_playback_speed_menu_type_summary_off">Old style flyout menu is used.</string>
<string name="revanced_custom_playback_speeds_title">Edit custom playback speeds</string>
<string name="revanced_custom_playback_speeds_summary">Add or change available playback speeds.</string>
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
<string name="revanced_remember_playback_speed_last_selected_summary_on">Playback speed changes apply to all videos.</string>
<string name="revanced_remember_playback_speed_last_selected_summary_off">Playback speed changes only apply to the current video.</string>
<string name="revanced_remember_playback_speed_last_selected_toast_title">Show a toast</string>
<string name="revanced_remember_playback_speed_last_selected_toast_summary_on">A toast will be shown when changing the default playback speed.</string>
<string name="revanced_remember_playback_speed_last_selected_toast_summary_off">A toast will not be shown when changing the default playback speed.</string>
<string name="revanced_custom_playback_speeds_invalid">Custom speeds must be less than %sx.</string>
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds.</string>
<!-- PreferenceScreen: Video, PreferenceCategory: Video quality -->
<string name="revanced_preference_category_video_quality">Video quality</string>
<string name="revanced_default_video_quality_mobile_title">Default video quality on mobile network</string>
<string name="revanced_default_video_quality_wifi_title">Default video quality on Wi-Fi network</string>
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
<string name="revanced_remember_video_quality_last_selected_summary_on">Quality changes apply to all videos.</string>
<string name="revanced_remember_video_quality_last_selected_summary_off">Quality changes only apply to the current video.</string>
<string name="revanced_remember_video_quality_last_selected_toast_title">Show a toast</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_on">A toast will be shown when changing the default video quality.</string>
<string name="revanced_remember_video_quality_last_selected_toast_summary_off">A toast will not be shown when changing the default video quality.</string>
<string name="revanced_default_video_quality_mobile_shorts_title">Default Shorts quality on mobile network</string>
<string name="revanced_default_video_quality_wifi_shorts_title">Default Shorts quality on Wi-Fi network</string>
<string name="revanced_remember_video_quality_shorts_last_selected_title">Remember Shorts quality changes</string>
<string name="revanced_remember_video_quality_shorts_last_selected_summary_on">Quality changes apply to all Shorts.</string>
<string name="revanced_remember_video_quality_shorts_last_selected_summary_off">Quality changes only apply to the current Short.</string>
<string name="revanced_remember_video_quality_shorts_last_selected_toast_title">Show a toast</string>
<string name="revanced_remember_video_quality_shorts_last_selected_toast_summary_on">A toast will be shown when changing the default Shorts quality.</string>
<string name="revanced_remember_video_quality_shorts_last_selected_toast_summary_off">A toast will not be shown when changing the default Shorts quality.</string>
<string name="revanced_remember_video_quality_mobile">mobile</string>
<string name="revanced_remember_video_quality_wifi">wifi</string>
<string name="revanced_remember_video_quality_toast">Changed default %1$s quality to: %2$s.</string>
<string name="revanced_remember_video_quality_toast_shorts">Changed Shorts %1$s quality to: %2$s.</string>
<string name="revanced_restore_old_video_quality_menu_title">Restore old video quality menu</string>
<string name="revanced_restore_old_video_quality_menu_summary_on">Old video quality menu is shown.</string>
<string name="revanced_restore_old_video_quality_menu_summary_off">Old video quality menu is not shown.</string>
<string name="revanced_disable_default_playback_speed_music_title">Disable playback speed for music</string>
<string name="revanced_disable_default_playback_speed_music_on">Default playback speed is disabled for music.</string>
<string name="revanced_disable_default_playback_speed_music_off">Default playback speed is enabled for music.</string>
<string name="revanced_disable_default_playback_speed_music_type_title">Validate using categories</string>
<string name="revanced_disable_default_playback_speed_music_type_on">Default playback speed is disabled if the video category is Music.</string>
<string name="revanced_disable_default_playback_speed_music_type_off">Default playback speed is disabled for videos playable on YouTube Music.</string>
<string name="revanced_enable_default_playback_speed_shorts_title">Enable Shorts default playback speed</string>
<string name="revanced_enable_default_playback_speed_shorts_summary_on">Default playback speed applies to Shorts.</string>
<string name="revanced_enable_default_playback_speed_shorts_summary_off">Default playback speed does not apply to Shorts.</string>
<string name="revanced_skipped_preloaded_buffer">Skipped preloaded buffer.</string>
<string name="revanced_skip_preloaded_buffer_title">Skip preloaded buffer</string>
<string name="revanced_skip_preloaded_buffer_summary">"Skips the preloaded buffer at the start of videos to immediately apply the default video quality.
@ -1814,26 +1855,18 @@ Info:
<string name="revanced_skip_preloaded_buffer_toast_summary_off">Toast is not shown.</string>
<string name="revanced_spoof_device_dimensions_title">Spoof device dimensions</string>
<string name="revanced_spoof_device_dimensions_summary">"Spoofs the device dimensions to the maximum value.
High quality may be unlocked on some videos that require high device dimensions, but not all videos."</string>
<string name="revanced_disable_vp9_codec_title">Disable VP9 codec</string>
<string name="revanced_disable_vp9_codec_summary_on">"VP9 codec is disabled.
• Maximum resolution is 1080p.
• Video playback will use more internet data than VP9.
• VP9 codec is still used for HDR video."</string>
<string name="revanced_disable_vp9_codec_summary_off">VP9 codec is enabled.</string>
<string name="revanced_replace_av1_codec_title">Replace software AV1 codec</string>
<string name="revanced_replace_av1_codec_summary">Replaces the software AV1 codec with the VP9 codec.</string>
<string name="revanced_reject_av1_codec_title">Reject software AV1 codec response</string>
<string name="revanced_reject_av1_codec_summary">"Forcefully rejects the software AV1 codec response.
A different codec will be applied after about 20 seconds of buffering."</string>
<string name="revanced_reject_av1_codec_toast">Fallback process causes about 20 seconds of buffering.</string>
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
<string name="revanced_remember_video_quality_mobile">Changing default mobile data quality to %s.</string>
<string name="revanced_remember_video_quality_none">Failed to set video quality.</string>
<string name="revanced_remember_video_quality_wifi">Changing default Wi-Fi quality to %s.</string>
<string name="revanced_custom_playback_speeds_invalid">Custom speeds must be less than %sx.</string>
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds.</string>
Info:
• High quality may be unlocked on some videos that require high device dimensions, but not all videos.
• This setting is not available if 'Spoof streaming data' is turned on."</string>
<!-- PreferenceScreen: Video, PreferenceCategory: Experimental flags -->
<string name="revanced_disable_default_playback_speed_music_title">Disable playback speed for music</string>
<string name="revanced_disable_default_playback_speed_music_on">Default playback speed is disabled for music.</string>
<string name="revanced_disable_default_playback_speed_music_off">Default playback speed is enabled for music.</string>
<string name="revanced_disable_default_playback_speed_music_type_title">Validate using categories</string>
<string name="revanced_disable_default_playback_speed_music_type_on">Default playback speed is disabled if the video category is Music.</string>
<string name="revanced_disable_default_playback_speed_music_type_off">Default playback speed is disabled for videos playable on YouTube Music.</string>
<!-- PreferenceScreen: Return YouTube Dislike -->

View File

@ -639,6 +639,7 @@
<SwitchPreference android:title="@string/revanced_shorts_custom_actions_copy_video_url_title" android:key="revanced_shorts_custom_actions_copy_video_url" android:summaryOn="@string/revanced_shorts_custom_actions_copy_video_url_summary_on" android:summaryOff="@string/revanced_shorts_custom_actions_copy_video_url_summary_off" />
<SwitchPreference android:title="@string/revanced_shorts_custom_actions_external_downloader_title" android:key="revanced_shorts_custom_actions_external_downloader" android:summaryOn="@string/revanced_shorts_custom_actions_external_downloader_summary_on" android:summaryOff="@string/revanced_shorts_custom_actions_external_downloader_summary_off" />
<SwitchPreference android:title="@string/revanced_shorts_custom_actions_open_video_title" android:key="revanced_shorts_custom_actions_open_video" android:summaryOn="@string/revanced_shorts_custom_actions_open_video_summary_on" android:summaryOff="@string/revanced_shorts_custom_actions_open_video_summary_off" />
<SwitchPreference android:title="@string/revanced_shorts_custom_actions_speed_dialog_title" android:key="revanced_shorts_custom_actions_speed_dialog" android:summaryOn="@string/revanced_shorts_custom_actions_speed_dialog_summary_on" android:summaryOff="@string/revanced_shorts_custom_actions_speed_dialog_summary_off" />
<SwitchPreference android:title="@string/revanced_shorts_custom_actions_repeat_state_title" android:key="revanced_shorts_custom_actions_repeat_state" android:summaryOn="@string/revanced_shorts_custom_actions_repeat_state_summary_on" android:summaryOff="@string/revanced_shorts_custom_actions_repeat_state_summary_off" />
<app.revanced.extension.youtube.settings.preference.ExternalDownloaderVideoPreference android:title="@string/revanced_external_downloader_package_name_video_title" android:key="revanced_external_downloader_package_name_video" android:summary="@string/revanced_external_downloader_package_name_video_summary" />
<Preference android:title="@string/revanced_shorts_custom_actions_about_title" android:selectable="false" android:summary="@string/revanced_shorts_custom_actions_about_summary" />SETTINGS: SHORTS_CUSTOM_ACTIONS_SHARED -->
@ -730,32 +731,44 @@
<!-- PREFERENCE_SCREEN: VIDEO
<PreferenceScreen android:title="@string/revanced_preference_screen_video_title" android:key="revanced_preference_screen_video">
<ListPreference android:title="@string/revanced_default_playback_speed_title" android:key="revanced_default_playback_speed" />
<ListPreference android:title="@string/revanced_default_video_quality_mobile_title" android:key="revanced_default_video_quality_mobile" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<ListPreference android:title="@string/revanced_default_video_quality_wifi_title" android:key="revanced_default_video_quality_wifi" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<PreferenceCategory android:title="@string/revanced_preference_category_codec" android:layout="@layout/revanced_settings_preferences_category"/>
<SwitchPreference android:title="@string/revanced_disable_hdr_video_title" android:key="revanced_disable_hdr_video" android:summaryOn="@string/revanced_disable_hdr_video_summary_on" android:summaryOff="@string/revanced_disable_hdr_video_summary_off" />
<SwitchPreference android:title="@string/revanced_enable_custom_playback_speed_title" android:key="revanced_enable_custom_playback_speed" android:summaryOn="@string/revanced_enable_custom_playback_speed_summary_on" android:summaryOff="@string/revanced_enable_custom_playback_speed_summary_off" />
<SwitchPreference android:title="@string/revanced_custom_playback_speed_menu_type_title" android:key="revanced_custom_playback_speed_menu_type" android:summaryOn="@string/revanced_custom_playback_speed_menu_type_summary_on" android:summaryOff="@string/revanced_custom_playback_speed_menu_type_summary_off" />
<app.revanced.extension.shared.settings.preference.ResettableEditTextPreference android:title="@string/revanced_custom_playback_speeds_title" android:key="revanced_custom_playback_speeds" android:summary="@string/revanced_custom_playback_speeds_summary" android:inputType="textMultiLine" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_last_selected_title" android:key="revanced_remember_playback_speed_last_selected" android:summaryOn="@string/revanced_remember_playback_speed_last_selected_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_last_selected_toast_title" android:key="revanced_remember_playback_speed_last_selected_toast" android:summaryOn="@string/revanced_remember_playback_speed_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_last_selected_toast_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_last_selected_title" android:key="revanced_remember_video_quality_last_selected" android:summaryOn="@string/revanced_remember_video_quality_last_selected_summary_on" android:summaryOff="@string/revanced_remember_video_quality_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_last_selected_toast_title" android:key="revanced_remember_video_quality_last_selected_toast" android:summaryOn="@string/revanced_remember_video_quality_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_video_quality_last_selected_toast_summary_off" />
<SwitchPreference android:title="@string/revanced_restore_old_video_quality_menu_title" android:key="revanced_restore_old_video_quality_menu" android:summaryOn="@string/revanced_restore_old_video_quality_menu_summary_on" android:summaryOff="@string/revanced_restore_old_video_quality_menu_summary_off" />
<PreferenceCategory android:title="@string/revanced_preference_category_experimental_flag" android:layout="@layout/revanced_settings_preferences_category"/>
<SwitchPreference android:title="@string/revanced_disable_default_playback_speed_music_title" android:key="revanced_disable_default_playback_speed_music" android:summaryOn="@string/revanced_disable_default_playback_speed_music_on" android:summaryOff="@string/revanced_disable_default_playback_speed_music_off" />
<SwitchPreference android:title="@string/revanced_disable_default_playback_speed_music_type_title" android:key="revanced_disable_default_playback_speed_music_type" android:summaryOn="@string/revanced_disable_default_playback_speed_music_type_on" android:summaryOff="@string/revanced_disable_default_playback_speed_music_type_off" />
<SwitchPreference android:title="@string/revanced_enable_default_playback_speed_shorts_title" android:key="revanced_enable_default_playback_speed_shorts" android:summaryOn="@string/revanced_enable_default_playback_speed_shorts_summary_on" android:summaryOff="@string/revanced_enable_default_playback_speed_shorts_summary_off" />
<SwitchPreference android:title="@string/revanced_skip_preloaded_buffer_title" android:key="revanced_skip_preloaded_buffer" android:summary="@string/revanced_skip_preloaded_buffer_summary" />
<SwitchPreference android:title="@string/revanced_skip_preloaded_buffer_toast_title" android:key="revanced_skip_preloaded_buffer_toast" android:summaryOn="@string/revanced_skip_preloaded_buffer_toast_summary_on" android:summaryOff="@string/revanced_skip_preloaded_buffer_toast_summary_off" android:dependency="revanced_skip_preloaded_buffer" />
<SwitchPreference android:title="@string/revanced_spoof_device_dimensions_title" android:key="revanced_spoof_device_dimensions" android:summary="@string/revanced_spoof_device_dimensions_summary" />
<SwitchPreference android:title="@string/revanced_disable_vp9_codec_title" android:key="revanced_disable_vp9_codec" android:summaryOn="@string/revanced_disable_vp9_codec_summary_on" android:summaryOff="@string/revanced_disable_vp9_codec_summary_off" />PREFERENCE_SCREEN: VIDEO -->
<!-- SETTINGS: REPLACE_AV1_CODEC
<SwitchPreference android:title="@string/revanced_replace_av1_codec_title" android:key="revanced_replace_av1_codec" android:summary="@string/revanced_replace_av1_codec_summary" />SETTINGS: REPLACE_AV1_CODEC -->
<!-- PREFERENCE_SCREEN: VIDEO
<SwitchPreference android:title="@string/revanced_reject_av1_codec_title" android:key="revanced_reject_av1_codec" android:summary="@string/revanced_reject_av1_codec_summary" />
<PreferenceCategory android:title="@string/revanced_preference_category_playback_speed" android:layout="@layout/revanced_settings_preferences_category"/>
<ListPreference android:title="@string/revanced_default_playback_speed_title" android:key="revanced_default_playback_speed" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_last_selected_title" android:key="revanced_remember_playback_speed_last_selected" android:summaryOn="@string/revanced_remember_playback_speed_last_selected_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_last_selected_toast_title" android:key="revanced_remember_playback_speed_last_selected_toast" android:summaryOn="@string/revanced_remember_playback_speed_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_last_selected_toast_summary_off" />
<ListPreference android:title="@string/revanced_default_playback_speed_shorts_title" android:key="revanced_default_playback_speed_shorts" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_shorts_last_selected_title" android:key="revanced_remember_playback_speed_shorts_last_selected" android:summaryOn="@string/revanced_remember_playback_speed_shorts_last_selected_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_shorts_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_playback_speed_shorts_last_selected_toast_title" android:key="revanced_remember_playback_speed_shorts_last_selected_toast" android:summaryOn="@string/revanced_remember_playback_speed_shorts_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_playback_speed_shorts_last_selected_toast_summary_off" />
<SwitchPreference android:title="@string/revanced_enable_custom_playback_speed_title" android:key="revanced_enable_custom_playback_speed" android:summaryOn="@string/revanced_enable_custom_playback_speed_summary_on" android:summaryOff="@string/revanced_enable_custom_playback_speed_summary_off" />
<SwitchPreference android:title="@string/revanced_custom_playback_speed_menu_type_title" android:key="revanced_custom_playback_speed_menu_type" android:summaryOn="@string/revanced_custom_playback_speed_menu_type_summary_on" android:summaryOff="@string/revanced_custom_playback_speed_menu_type_summary_off" />
<app.revanced.extension.shared.settings.preference.ResettableEditTextPreference android:title="@string/revanced_custom_playback_speeds_title" android:key="revanced_custom_playback_speeds" android:summary="@string/revanced_custom_playback_speeds_summary" android:inputType="textMultiLine" />
<PreferenceCategory android:title="@string/revanced_preference_category_video_quality" android:layout="@layout/revanced_settings_preferences_category"/>
<ListPreference android:title="@string/revanced_default_video_quality_mobile_title" android:key="revanced_default_video_quality_mobile" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<ListPreference android:title="@string/revanced_default_video_quality_wifi_title" android:key="revanced_default_video_quality_wifi" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_last_selected_title" android:key="revanced_remember_video_quality_last_selected" android:summaryOn="@string/revanced_remember_video_quality_last_selected_summary_on" android:summaryOff="@string/revanced_remember_video_quality_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_last_selected_toast_title" android:key="revanced_remember_video_quality_last_selected_toast" android:summaryOn="@string/revanced_remember_video_quality_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_video_quality_last_selected_toast_summary_off" />
<ListPreference android:title="@string/revanced_default_video_quality_mobile_shorts_title" android:key="revanced_default_video_quality_mobile_shorts" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<ListPreference android:title="@string/revanced_default_video_quality_wifi_shorts_title" android:key="revanced_default_video_quality_wifi_shorts" android:entries="@array/revanced_default_video_quality_entries" android:entryValues="@array/revanced_default_video_quality_entry_values" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_shorts_last_selected_title" android:key="revanced_remember_video_quality_shorts_last_selected" android:summaryOn="@string/revanced_remember_video_quality_shorts_last_selected_summary_on" android:summaryOff="@string/revanced_remember_video_quality_shorts_last_selected_summary_off" />
<SwitchPreference android:title="@string/revanced_remember_video_quality_shorts_last_selected_toast_title" android:key="revanced_remember_video_quality_shorts_last_selected_toast" android:summaryOn="@string/revanced_remember_video_quality_shorts_last_selected_toast_summary_on" android:summaryOff="@string/revanced_remember_video_quality_shorts_last_selected_toast_summary_off" />
<SwitchPreference android:title="@string/revanced_restore_old_video_quality_menu_title" android:key="revanced_restore_old_video_quality_menu" android:summaryOn="@string/revanced_restore_old_video_quality_menu_summary_on" android:summaryOff="@string/revanced_restore_old_video_quality_menu_summary_off" />
<SwitchPreference android:title="@string/revanced_skip_preloaded_buffer_title" android:key="revanced_skip_preloaded_buffer" android:summary="@string/revanced_skip_preloaded_buffer_summary" />
<SwitchPreference android:title="@string/revanced_skip_preloaded_buffer_toast_title" android:key="revanced_skip_preloaded_buffer_toast" android:summaryOn="@string/revanced_skip_preloaded_buffer_toast_summary_on" android:summaryOff="@string/revanced_skip_preloaded_buffer_toast_summary_off" android:dependency="revanced_skip_preloaded_buffer" />
<SwitchPreference android:title="@string/revanced_spoof_device_dimensions_title" android:key="revanced_spoof_device_dimensions" android:summary="@string/revanced_spoof_device_dimensions_summary" />
<PreferenceCategory android:title="@string/revanced_preference_category_experimental_flag" android:layout="@layout/revanced_settings_preferences_category"/>
<SwitchPreference android:title="@string/revanced_disable_default_playback_speed_music_title" android:key="revanced_disable_default_playback_speed_music" android:summaryOn="@string/revanced_disable_default_playback_speed_music_on" android:summaryOff="@string/revanced_disable_default_playback_speed_music_off" />
<SwitchPreference android:title="@string/revanced_disable_default_playback_speed_music_type_title" android:key="revanced_disable_default_playback_speed_music_type" android:summaryOn="@string/revanced_disable_default_playback_speed_music_type_on" android:summaryOff="@string/revanced_disable_default_playback_speed_music_type_off" />
</PreferenceScreen>PREFERENCE_SCREEN: VIDEO -->