fix(YouTube Music - Spoof streaming data): Fix audio playback stuttering (#5839)

This commit is contained in:
LisoUseInAIKyrios 2025-09-14 22:19:13 +04:00 committed by GitHub
parent eee72208dd
commit 2a85a3b290
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 174 additions and 82 deletions

View file

@ -6,8 +6,6 @@ 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.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.spoof.ClientType;
/**
@ -36,18 +34,5 @@ public class BaseSettings {
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));
static {
// Data migration fix for YT Music users updating from very old patches that always
// stored default values in preference object, which requires manually updating
// the setting if the default changes. Package name may not contain "youtube.music"
// if the user has used change package name patch, but this will detect users
// with default installations.
if (!SPOOF_VIDEO_STREAMS_CLIENT_TYPE.isSetToDefault()
&& Utils.getContext().getPackageName().contains("youtube.music")) {
Logger.printInfo(() -> "Resetting spoof client from: " + SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
SPOOF_VIDEO_STREAMS_CLIENT_TYPE.resetToDefault();
}
}
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

@ -12,7 +12,7 @@ import app.revanced.extension.shared.settings.BaseSettings;
public enum ClientType {
// 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,7 +27,7 @@ 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
@ -96,6 +96,26 @@ public enum ClientType {
forceAVC()
? "iOS TV Force AVC"
: "iOS TV"
),
/**
* Uses non adaptive bitrate, which fixes audio stuttering with YT Music.
* Uses VP9 and not AV1.
*/
ANDROID_VR_1_43_32(
ANDROID_VR_1_61_48.id,
ANDROID_VR_1_61_48.clientName,
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,
ANDROID_VR_1_61_48.androidSdkVersion,
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"
);
private static boolean forceAVC() {

View file

@ -252,8 +252,9 @@ public class SpoofVideoStreamsPatch {
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
ClientType clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
&& (clientType == ClientType.ANDROID_VR_1_61_48 || clientType == ClientType.ANDROID_VR_1_43_32);
}
}

View file

@ -42,7 +42,8 @@ final class PlayerRoutes {
// 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
Locale streamLocale = (userSelectedClient == ClientType.ANDROID_VR_1_61_48
|| userSelectedClient == ClientType.ANDROID_VR_1_43_32)
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getLocale()
: Locale.getDefault();

View file

@ -35,21 +35,22 @@ 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(ClientType[] availableClients, ClientType preferredClient) {
Objects.requireNonNull(availableClients);
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
CLIENT_ORDER_TO_USE[0] = preferredClient;
clientOrderToUse = new ClientType[availableClients.length];
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 +194,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) {