// ==UserScript== // @name Youtube AD Skipper 油管广告拦截跳过 // @name:zh-CN Youtube AD Skipper 油管广告拦截跳过 // @namespace http://tampermonkey.net/ // @version 0.1 // @description Quickly skip video ads in Youtube. 快速跳过油管中的视频广告。 // @description:zh-CN Quickly skip video ads in Youtube. 快速跳过油管中的视频广告。 // @icon https://www.gstatic.com/youtube/img/branding/favicon/favicon_144x144.png // @author gabe // @license MIT // @match https://*.youtube.com/* // @grant none // @downloadURL none // ==/UserScript== (function () { "use strict"; function sleep(delay = 100) { return new Promise(function (resolve) { const timer = setTimeout(function () { clearTimeout(timer); resolve(); }, delay); }); } async function skipAd(moviePlayer, adOverlay) { let i = 0; while (true) { i++; if (i > 1) { adOverlay = moviePlayer.getElementsByClassName( "ytp-ad-player-overlay" )[0]; if (!adOverlay) { return; } } const skipButton = adOverlay.getElementsByClassName("ytp-ad-skip-button")[0]; const isMobile = location.hostname === "m.youtube.com"; if (!isMobile && skipButton) { skipButton.click(); console.info("[Youtube AD Skipper] Ad skipped ->", i); await sleep(); continue; } const video = moviePlayer.getElementsByTagName("video")[0]; video.currentTime = video.duration; console.info("[Youtube AD Skipper] Ad stopped ->", i); await sleep(); } } let isBusying = false; const pageObserver = new MutationObserver(async function () { if (isBusying) { return; } const moviePlayer = document.getElementById("movie_player"); if (!moviePlayer) { return; } const adOverlay = moviePlayer.getElementsByClassName( "ytp-ad-player-overlay" )[0]; if (!adOverlay) { return; } isBusying = true; const adInfo = adOverlay.getElementsByClassName( "ytp-ad-player-overlay-instream-info" )[0]; console.info("[Youtube AD Skipper] Ad found: ", adInfo && adInfo.innerText); await skipAd(moviePlayer, adOverlay); isBusying = false; }); pageObserver.observe(document.body, { childList: true, subtree: true, }); })();