您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sick of outros on your favourite creators videos? With this script simply set the outro length in seconds, apply and enjoy!
当前为
// ==UserScript== // @name Youtube outro skip // @namespace http://tampermonkey.net/ // @version 1.5 // @description Sick of outros on your favourite creators videos? With this script simply set the outro length in seconds, apply and enjoy! // @author Daile Alimo // @match https://www.youtube.com/watch?* // @grant GM_setValue // @grant GM_getValue // @require http://code.jquery.com/jquery-latest.js // ==/UserScript== let destroy = function(){ // // make sure we have no events binded, in the case fn() was called by interval on URL change // this will ensure that we can create clean controls for the current playlist without accidentally // having events persisting in the background. // if ($(".video-stream").unbind()) {console.log("unbinding .video-stream");} if ($("#set-outro").unbind()){console.log("unbinding #set-outro");} if ($(".outro-controls").remove()){console.log("removed controls");} } // whenReady - keep checking the DOM until these given selectors are found // invokes a callback function on complete that contains an object containing the // JQuery element(s) for the given selectors accessable with aliases if given. const whenReady = ({selectors = [], aliases = [], callback = (selectors = {})}) => { let ready = {}; let found = 0; for(let i in selectors){ let $sel = $(selectors[i]); if ($sel.length) { let index = aliases[i] ? aliases[i]: i; console.log("added selector: " + index); ready[index] = $sel; found++; } } console.log(found + " out of given " + selectors.length + " selector(s) found"); if (found === selectors.length) { return callback(ready); } setTimeout(function(){ console.log("waiting for " + (selectors.length - found) + " selector(s)"); whenReady({ selectors: selectors, aliases: aliases, callback: callback }); }, 500); }; (function(fn){ "use strict"; // $(document).ready(function(){ fn(); }); // // detect page change hashchange not working // so check every 3 seconds if current URL matches URL we started with. // handle appropriately. // var l = document.URL; setInterval(function(){ if (l != document.URL){ l = document.URL; destroy(); if (l === "https://www.youtube.com/") { // ignore home, no controls here return; } fn(); } }, 3000); })(function(){ whenReady({ selectors: [".video-stream", "#primary", ".ytp-settings-menu .ytp-panel-menu", "#meta-contents #text.ytd-channel-name,.ytp-ce-channel-title"], aliases: ["stream", "container", "settings", "channel"], callback: (selectors) => { // let channel = selectors.channel.first().text(); console.log("loaded channel: " + channel); // let urlString = document.URL + '&'; // let isPlaylist = urlString.includes("list") let loadedChannel = true; let targetId = channel.split(" ").join("_"); if (isPlaylist && !GM_getValue(targetId)) { console.log("using playlist outro settings"); loadedOutroSetInSeconds = GM_getValue(urlString.match(/[\?\&]list=([^\&\#]+)[\&\#]/i)[1]); loadedChannel = false; } // var loadedOutroSetInSeconds = GM_getValue(targetId); console.log("outro set: " + (loadedOutroSetInSeconds || 0)); // // basic outro controls design prepended to the primary container. // if property length doesn't exist we can assume controls don't either. // prepend controls to #primary container // let target = isPlaylist? "playlist" : channel; console.log("target set " + (loadedChannel? "channel": "playlist") + " = " + targetId); console.log("writing outro controls"); selectors.container.prepend( $("<div class='outro-controls'>").append( $("<h3>Youtube Skip Outro Controller V1.1</h3>") ).append( $("<input type='number' id='outro-length' placeholder='using id: " + targetId + "'/>") ).append( $("<button id='set-outro'>apply</button>") ).append( $("<div>" + target + " outro set: <span id='outro-set'>0</span> seconds</div>").css({ "padding": "2px", }) ).css({ "margin": "2px", "textAlign": "right", }) ); // let bindToStream = function(){ // hook video timeupdate, wait for outro and hit next button when time reached // if(loadedOutroSetInSeconds){ var skipOutroSeconds = parseInt(loadedOutroSetInSeconds) | 0; selectors.stream.unbind("timeupdate").on("timeupdate", function(e){ var currentTime = this.currentTime; var duration = this.duration; if(currentTime >= duration - skipOutroSeconds){ $(".ytp-next-button")[0].click(); } }); $("#outro-set").text(loadedOutroSetInSeconds); } } // // handle apply outro in seconds // $("#set-outro").on("click", function(e){ var seconds = $("#outro-length").val().toString(); if(seconds && seconds != "" && parseInt(seconds) != NaN){ GM_setValue(targetId, seconds); loadedOutroSetInSeconds = seconds; bindToStream(); } }); bindToStream(); }, }); });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址