revanced-patches-template
revanced-patches-template copied to clipboard
feat: `disable-auto-captions` patch
🐞 Issue
YouTube turn on captions (chosen based on the current region) automatically at the beginning of some videos.
❗ Solution
Adapt the following POC to ReVanced patches:
public static void ForcedInitCaption()
{
ConsoleLog.Divider();
ConsoleLog.StartPatch("Patching Forced Init Captions in progress...");
string[] allFiles = Directory.GetFiles(Main.apkDecompiledPath, "*.smali*", SearchOption.AllDirectories);
string firstReference = "\"pc\"";
string secondReference = APKOps.GetResourceID("drawable", "quantum_ic_closed_caption_white_24");
string thirdReference = "\"DISABLE_CAPTIONS_OPTION\"";
string firstSubReference = ".method";
string secondSubReference = "(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;";
string thirdSubReference = ".locals";
string fourthSubReference = "# static fields";
string fifthSubReference = "()Z";
bool firstReferencePatched = false;
bool secondReferencePatched = false;
bool thirdReferencePatched = false;
foreach (string file in allFiles)
{
string fullContent = File.ReadAllText(file);
List<string> lines = new List<string>();
if (!firstReferencePatched)
{
if (fullContent.Contains(firstReference))
{
lines = File.ReadAllLines(file).ToList();
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains(firstReference))
{
for (int j = i; j >= 0; j--)
{
if (lines[j].Contains(firstSubReference) &&
lines[j].Contains(secondSubReference))
{
ConsoleLog.Found($"Found file: {Path.GetFileNameWithoutExtension(file)}", true);
string[] firstPatch = {
"const/4 v0, 0x0",
"sput-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z"
};
lines.InsertRange(j + 2, firstPatch);
File.WriteAllLines(file, lines);
firstReferencePatched = true;
break;
}
}
if (firstReferencePatched)
{
break;
}
}
}
}
}
if (!secondReferencePatched)
{
if (file.Contains("SubtitleButtonController.smali"))
{
lines = File.ReadAllLines(file).ToList();
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains(secondReference))
{
for (int j = i; j >= 0; j--)
{
if (lines[j].Contains(thirdSubReference))
{
ConsoleLog.Found($"Found file: {Path.GetFileNameWithoutExtension(file)}", true);
string[] secondPatch = {
"const/4 v0, 0x1",
"sput-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z"
};
lines.InsertRange(j + 1, secondPatch);
File.WriteAllLines(file, lines);
secondReferencePatched = true;
break;
}
}
if (secondReferencePatched)
{
break;
}
}
}
}
}
if (!thirdReferencePatched)
{
if (file.Contains("SubtitleTrack.smali"))
{
lines = File.ReadAllLines(file).ToList();
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains(fourthSubReference))
{
string[] thirdSubPatch = {
".field public static disablecaption:Z"
};
lines.InsertRange(i + 1, thirdSubPatch);
}
if (lines[i].Contains(thirdReference))
{
for (int j = i; j >= 0; j--)
{
if (lines[j].Contains(firstSubReference) &&
lines[j].Contains(fifthSubReference))
{
ConsoleLog.Found($"Found file: {Path.GetFileNameWithoutExtension(file)}", true);
string[] thirdPatch = {
"sget-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z",
"if-nez v0, :cond_disableinitcaption",
"const/4 v0, 0x1",
"return v0",
":cond_disableinitcaption"
};
lines.InsertRange(j + 2, thirdPatch);
File.WriteAllLines(file, lines);
thirdReferencePatched = true;
break;
}
}
if (thirdReferencePatched)
{
break;
}
}
}
}
}
if (firstReferencePatched &&
secondReferencePatched &&
thirdReferencePatched)
{
break;
}
}
if (!firstReferencePatched)
{
ConsoleLog.EndPatch("Error during searching and patching the first reference", false);
}
if (!secondReferencePatched)
{
ConsoleLog.EndPatch("Error during searching and patching the second reference", false);
}
if (!thirdReferencePatched)
{
ConsoleLog.EndPatch("Error during searching and patching the third reference", false);
}
if (firstReferencePatched &&
secondReferencePatched &&
thirdReferencePatched)
{
ConsoleLog.EndPatch("Forced Init Captions succesfully patched", true);
}
else
{
Main.buildingFailed = true;
}
}
❓ Motivation
This mod may be useful for those who intend to have as few interactions as possible with their device.
I have tried it but this did not work for me.
I have tried it but this did not work for me.
It working flawlessly for me.
Are you sure you have tested it on a video that automatically activates the captions? Otherwise nothing changes.
Can you send one?
Can you send one?
Already done in private, but it doesn't seem to work for everyone.
In any case, I'll try again:
The videos of this channel contains auto-captions:
https://youtu.be/NkHH4LX_kRg
And this channel too:
https://youtu.be/3F5cV98isaY
Works.
Works.
Would have been very weird if it only worked on my device xD
What is that code? Thats not referring to our Patcher?
What is that code? Thats not referring to our Patcher?
This is code from my C# patcher.
I hate kotlin for various reason, first of all my inability to write a patch.
You can adapt the code if you want.
Just add a toggle to disable patch, at this point:
sget-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z
if-nez v0, :cond_disableinitcaption
const/4 v0, 0x1
return v0
:cond_disableinitcaption
What is that code? Thats not referring to our Patcher?
This is code from my C# patcher.
I hate kotlin for various reason, first of all my inability to write a patch.
You can adapt the code if you want.
Just add a toggle to disable patch, at this point:
sget-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z if-nez v0, :cond_disableinitcaption const/4 v0, 0x1 return v0 :cond_disableinitcaption
So thats the same which vanced did, so we would have done this anyway, but thanks for helping us out :)
What is that code? Thats not referring to our Patcher?
This is code from my C# patcher. I hate kotlin for various reason, first of all my inability to write a patch. You can adapt the code if you want. Just add a toggle to disable patch, at this point:
sget-boolean v0, Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;->disablecaption:Z if-nez v0, :cond_disableinitcaption const/4 v0, 0x1 return v0 :cond_disableinitcaptionSo thats the same which vanced did, so we would have done this anyway, but thanks for helping us out :)
Nope... This was deprecated starting from vanced 15.xx, despite Vanced Team keep the reference inside settings.
The proof is there's no patch like that on Vanced 17.03.38.
This would be way easier if you would actually provide class and method names :)
This would be way easier if you would actually provide class and method names :)
Based on which version?
The one from the docs
This would be way easier if you would actually provide class and method names :)
17.27.39 --->
First reference: {method: public final void d, class: aamt.smali}
Second reference: {method: public final void D, class: SubtitleButtonController.smali}
Third reference: {method: public final boolean t, class: SubtitleTrack.smali}
Thanks, I can work with that now :)
Patch is not possible to create. Theres no way to generate a safe fingerprint for class aamt.
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
not possible. Those methods have no usages. Thats at least what jadx says.
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
not possible. Those methods have no usages. Thats at least what jadx says.
Searching for string:
"pc"
And after searching for method
"(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
Anyway...I posted the PoC for a reason.
All these infos was already listed there.
And after searching for method
"(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
Returns 0 results.
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
not possible. Those methods have no usages. Thats at least what jadx says.
The class has, and since the class has you can get it from a parent method.
And after searching for method "(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
Returns 0 results.
Instead this returns me, on my patcher at least, a method with the aformentioned variables. 🤷♂️
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
not possible. Those methods have no usages. Thats at least what jadx says.
Searching for string:
"pc"
"pc" is not contained in the class
The class has, and since the class has you can get it from a parent method.
I'll check again tomorrow then
Not required, you can create a parent fingerprint for a different method which references this one and use the method walker.
not possible. Those methods have no usages. Thats at least what jadx says.
Searching for string: "pc"
"pc" is not contained in the class
LOL

And after searching for method "(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
Returns 0 results.
Instead this returns me, on my patcher at least, a method with the aformentioned variables. 🤷♂️
Open jadx, go to mentioned class, open smali view, Ctrl+f, search, and find nothing. Your patcher is not revanced. So We have to find a working way.
And after searching for method "(Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
Returns 0 results.
Instead this returns me, on my patcher at least, a method with the aformentioned variables. 🤷♂️
Open jadx, go to mentioned class, open smali view, Ctrl+f, search, and find nothing. Your patcher is not revanced. So We have to find a working way.
Already done.
You can see the screenshot in the answer preceding yours.