Greasy Fork

Greasy Fork is available in English.

Youtube AD Skipper 油管广告拦截跳过

Quickly skip video ads in Youtube. 快速跳过油管中的视频广告。

目前为 2023-10-30 提交的版本。查看 最新版本

// ==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
// ==/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,
  });
})();