Greasy Fork is available in English.
Allow to choose the default speed for specific YT channel
< Feedback on Youtube Speed By Channel
Need more details. It's still working for me on Firefox + Tampermonkey + Windows.
Windows 10 Pro
Firefox 109 x64
Tampermonkey 4.18.1 + This script 0.2.7 (the only script I have installed)
Tampermonkey's toolbar button indicates that 1 script is active, but the speed buttons at the bottom of the player are missing.
BUT, if I sign out of my Google account and start using YouTube anonymously the buttons are back !!!
Is it possible that Google is serving my account a modified version of the player?
See if this update changes anything. Also look on the firefox console for any errors that might be related to the script. CTRL + SHIFT + K to open it. then CTRL + F5 to update the page.
Nope, nothing changed.
No errors from the script, even the console.log entries are missing.
I played around with the script adding debug console outputs and I think I might be onto something.
Please see Att 1 showing the debug lines I added to the script.
It seems that when I try to watch YouTube video logged in with my account the page source code is slightly different and "channeldiv.length" is always equal to Zero forcing the function "youtube()" to exit by this line: "if (!channeldiv.length) return;" - please see Att 2.
When I LogOut from YouTube and watch the same video as anonymous then "channeldiv.length" equals 2 and the script works fine - see Att 3.
I sought out (or I hope I did) the relevant part in the page source code and copied it - see Att 4 (top - Logged-in user; bottom - Anonymous user). vsb-channel="0" parameter is missing from the LoggedIn version of the source code. There are some other differences too.
Thanks. Really helpful. See if changing
el.closest('ytd-watch-flexy').find('#upload-info #channel-name')
to
el.closest('ytd-watch-flexy').find('#upload-info ytd-channel-name')
or
el.closest('ytd-watch-flexy').find('ytd-channel-name')
works.
If not. Please try to show about the same part of the source code on your last image, but when you are logged in.
If you cannot find it, right click on the channel name (MrSubaru1387 on your first post image), press Q. Then right clicking the selected element on the window that will open > Copy > CSSPath. And paste it here. While logged in as well.
Sorry for all this trouble. But since I'm not yet being served the same youtube page, I can't do much alone.
Logged in:
----------------------
html body ytd-app div#content.style-scope.ytd-app ytd-page-manager#page-manager.style-scope.ytd-app ytd-watch-flexy.style-scope.ytd-page-manager.hide-skeleton div#columns.style-scope.ytd-watch-flexy div#primary.style-scope.ytd-watch-flexy div#primary-inner.style-scope.ytd-watch-flexy div#below.style-scope.ytd-watch-flexy ytd-watch-metadata.watch-active-metadata.style-scope.ytd-watch-flexy div#above-the-fold.style-scope.ytd-watch-metadata div#top-row.style-scope.ytd-watch-metadata div#owner.item.style-scope.ytd-watch-metadata ytd-video-owner-renderer.style-scope.ytd-watch-metadata div#upload-info.style-scope.ytd-video-owner-renderer ytd-channel-name#channel-name.style-scope.ytd-video-owner-renderer div#container.style-scope.ytd-channel-name div#text-container.style-scope.ytd-channel-name yt-formatted-string#text.style-scope.ytd-channel-name.complex-string a.yt-simple-endpoint.style-scope.yt-formatted-string
Anonymous:
------------------
html body ytd-app div#content.style-scope.ytd-app ytd-page-manager#page-manager.style-scope.ytd-app ytd-watch-flexy.style-scope.ytd-page-manager.hide-skeleton div#columns.style-scope.ytd-watch-flexy div#primary.style-scope.ytd-watch-flexy div#primary-inner.style-scope.ytd-watch-flexy div#below.style-scope.ytd-watch-flexy ytd-watch-metadata.watch-active-metadata.style-scope.ytd-watch-flexy div#above-the-fold.style-scope.ytd-watch-metadata div#top-row.style-scope.ytd-watch-metadata div#owner.item.style-scope.ytd-watch-metadata ytd-video-owner-renderer.style-scope.ytd-watch-metadata div#upload-info.style-scope.ytd-video-owner-renderer ytd-channel-name#channel-name.style-scope.ytd-video-owner-renderer div#container.style-scope.ytd-channel-name div#text-container.style-scope.ytd-channel-name yt-formatted-string#text.style-scope.ytd-channel-name.complex-string a.yt-simple-endpoint.style-scope.yt-formatted-string
There is no difference if I get this information by the method you described.
Please download this txt file with the actual snippets of code:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/Snippets.txt
I think that for some reason "el.closest('ytd-watch-flexy')" isn't traversing upstream the path to object 'ytd-watch-flexy'. No matter what object I put in the apostrophes the result is the same (for example "ytd-app" or even "#primary-inner"). The moment I log out the script starts to work with these objects.
"this" is also slightly different when logged-in or anonymous. You can download a txt file from here:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/ThisObject.txt
Very weird that there's no difference on CSSPath.
I will try traversing using parent() until it finds what it needs.
Try adding this:
if (!channeldiv.length){ let el2 = el; while (!channeldiv.length && el2.length && el2[0].tagName !== "BODY"){ el2 = el2.parent(); channeldiv = el2.find('#upload-info #channel-name'); } }
Before:
if (!channeldiv.length) return;
It doesn't work.
I added some additional debugging code to see what's happening:
Debugging code added to function youtube():
---------------------------------------------
function youtube(){
$('#movie_player:visible:not([monitored]), #c4-player:visible:not([monitored])').each(async function( index ) {
let el = $(this);
let speed, channelspeed;
console.error('!!!!!! Debug data 1 !!!!!!!!!!!');
console.error(el.length);
console.error(el);
if (this.id === "movie_player" && !this.classList.contains('ytp-player-minimized')){
let channeldiv = el.closest('ytd-watch-flexy').find('#upload-info #channel-name');
if (!channeldiv.length){
let el2 = el;
while (!channeldiv.length && el2.length && el2[0].tagName !== "BODY"){
el2 = el2.parent();
console.error('!!!!!! Debug data 2 !!!!!!!!!!!');
console.error(el2.length);
console.error(el2);
channeldiv = el2.find('#upload-info #channel-name');
}
}
console.error('!!!!!! Debug data 3 !!!!!!!!!!!');
console.error(channeldiv.length);
console.error(channeldiv);
if (!channeldiv.length) return;
...
This is the result in Console (for logged-in and anonymous user):
Logged-in account debug data:
-----------------------------------------
!!!!!! Debug data 1 !!!!!!!!!!!
Object { 0: div#movie_player.html5-video-player.ytp-transparent.ytp-exp-bottom-control-flexbox.ytp-exp-ppp-update.ad-created.ytp-fit-cover-video.ytp-fine-scrubbing-exp.ytp-large-width-mode.ytp-rounded-miniplayer.style-scope.ytd-player.ytp-hide-info-bar.ytp-autonav-endscreen-cancelled-state.paused-mode, length: 1 }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player-api, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player-wrap, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player.skeleton.flexy, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: body, length: 1, prevObject: {…} }
!!!!!! Debug data 3 !!!!!!!!!!!
Object { length: 0, prevObject: {…} }
length: 0
prevObject: Object { 0: body, length: 1, prevObject: {…} }
: Object { jquery: "3.6.0", constructor: S(e, t), length: 0, … }
^ This section repeats several times and is ALWAYS followed by this section (indefinitely):
!!!!!! Debug data 1 !!!!!!!!!!!
Object { 0: div#movie_player.html5-video-player.ytp-transparent.ytp-exp-bottom-control-flexbox.ytp-exp-ppp-update.ad-created.ytp-fit-cover-video.ytp-fine-scrubbing-exp.ytp-large-width-mode.ytp-rounded-miniplayer.style-scope.ytd-player.ytp-hide-info-bar.ytp-autonav-endscreen-cancelled-state.paused-mode, length: 1 }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#container.style-scope.ytd-player, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { length: 0, prevObject: {…} }
!!!!!! Debug data 3 !!!!!!!!!!!
Object { length: 0, prevObject: {…} }
^ This section repeats indefinitely until all RAM is consumed.
Anonymous user debug data:
-----------------------------------------
!!!!!! Debug data 1 !!!!!!!!!!!
Object { 0: div#movie_player.html5-video-player.ytp-transparent.ytp-exp-bottom-control-flexbox.ytp-exp-ppp-update.ad-created.ytp-fit-cover-video.ytp-fine-scrubbing-exp.ytp-hide-info-bar.ytp-large-width-mode.ytp-rounded-miniplayer.ytp-autonav-endscreen-cancelled-state.playing-mode.unstarted-mode, length: 1 }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player-api, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player-wrap, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: div#player.skeleton.flexy, length: 1, prevObject: {…} }
!!!!!! Debug data 2 !!!!!!!!!!!
Object { 0: body, length: 1, prevObject: {…} }
!!!!!! Debug data 3 !!!!!!!!!!!
Object { length: 0, prevObject: {…} }
^ This section repeats several times and is ALWAYS followed by this section (once):
!!!!!! Debug data 1 !!!!!!!!!!!
Object { 0: div#movie_player.html5-video-player.ytp-transparent.ytp-exp-bottom-control-flexbox.ytp-exp-ppp-update.ad-created.ytp-fit-cover-video.ytp-fine-scrubbing-exp.ytp-hide-info-bar.ytp-large-width-mode.ytp-rounded-miniplayer.ytp-autonav-endscreen-cancelled-state.playing-mode.unstarted-mode, length: 1 }
!!!!!! Debug data 3 !!!!!!!!!!!
Object { 0: ytd-channel-name#channel-name.style-scope.ytd-video-owner-renderer, 1: ytd-channel-name#channel-name.style-scope.ytd-video-owner-renderer, length: 2, prevObject: {…} }
Adding video-id observer
Object { chosenspeed: 1, chosenreason: "default" }
- The console log ends here and the script starts working.
This video was used for the debugging process:
https://www.youtube.com/watch?v=2mhlIBLTY5c
What is "#player.skeleton.flexy"? This must have been introduced dynamically by a script??
Sory for the lack of formatting. The system doesn't allow me to edit my comment and add the PRE tag...
Here is the txt file if you need it:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/Debug3.txt
Sory for the lack of formatting. The system doesn't allow me to edit my comment and add the PRE tag...
Here is the txt file if you need it:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/Debug3.txt
Don't worry. I was able to understand it.
Very weird.
Would you be comfortable to send me the entire page source code while logged in? If so, right click on the video page and click on "View page source" and send it.
This doesn't give me access to your account in any way. It just allows me to see the static page and debug myself. Maybe it would be easier to find the issue.
I'm still trying to find what the issue could be.
Here you are, although I'm not sure the View Page Source gives the actual source code:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/ViewPageSource.zip
I saved the page source through the Inspector and the source seems to be much more complete:
https://cloud.dontcheff.eu/index.php/apps/sharingpath/ablazhov/Public/InspectorExport.zip
Could you confirm you can download those files I'm uploading in the cloud?
Download it. I will look into it now.
Downloaded it*.
Maybe
if (!channeldiv.length) channeldiv = $('ytd-watch-metadata #upload-info #channel-name');
before
if (!channeldiv.length) return;
?
Nevermind. I think it will fail elsewhere. Still looking into it.
It didn't help :-(
I don't understand why the traversing isn't following the nested structure but instead is reporting these objects from the debug log:
#player-api, #player-wrap, #player.skeleton.flexy...
Maybe we should wait for this modified version of the page code to become more widespread so that you can examine it firsthandedly...?
Yeah, it's very weird. It should be working.
Is the output of channeldiv in
if (!channeldiv.length) channeldiv = $('ytd-watch-metadata #upload-info #channel-name');
still returning empty?
It should find something like this. Maybe it failed elsewhere. I found an issue in the getchannelname function using your page. Added a fix to it as well. Update and see if we got lucky.
If not, I'll keep trying to find the issue, don't worry. Maybe even scheduling a rewrite of some parts of the code.
The output of channeldiv is empty the first several times, but the last time returns this:
Object { 0: ytd-channel-name#channel-name.style-scope.ytd-video-owner-renderer, length: 1, prevObject: {…} } 0: <*ytd-channel-name id="channel-name" class="style-scope ytd-video-owner-renderer" vsb-channel="0"> "$": Object { text: yt-formatted-string#text.style-scope.ytd-channel-name.complex-string, "text-container": div#text-container.style-scope.ytd-channel-name, container: div#container.style-scope.ytd-channel-name }
Look for this debug tag: !!!!!! Debug data 3 !!!!!!!!!!!
No more infinite loops.
And then something crashes:
Uncaught (in promise) TypeError: MutationObserver.observe
This is great. Some progress.
I think I fixed this MutationObserver issue now.
Yup, everything works now! Great!
Hats down to you, alpe!!
I cannot update to 0.2.12 nor can I install 0.2.12 from scratch!
Every time I get 0.2.11 ...
Had to manually replace the code.
Maybe greasyfork is slow and hasn't pushed it correctly yet.
But, latest works right?
Assuming yes:
Awesome. Still don't know why jQuery is misbehaving.
Happy that it works now.
Sorry for all the trouble I gave you because I'm not receiving the same page.
Any problems in the future feel free to report.
Yes, 0.2.12 works!
Great work!
Thanks!
The script stopped working for me (Firefox + Windows).