Greasy Fork

Greasy Fork is available in English.

YouTube Ad Skipper

Automatically skip ads on YouTube with advanced options and performance improvements

当前为 2024-08-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name             YouTube Ad Skipper
// @name:en          YouTube Ad Skipper
// @name:vi          Trình Tự Động Bỏ Qua Quảng Cáo YouTube 
// @name:zh-cn       YouTube 广告跳过器
// @name:zh-tw       YouTube 廣告跳過器
// @name:ja          YouTube 広告スキッパー
// @name:ko          YouTube 광고 건너뛰기
// @name:es          Saltador de Anuncios de YouTube Mejorado
// @name:ru          Улучшенный пропуск рекламы на YouTube
// @name:id          YouTube Ad Skipper
// @name:hi          YouTube विज्ञापन स्किपर
// @namespace        http://tampermonkey.net/
// @version          1.4.0
// @description      Automatically skip ads on YouTube with advanced options and performance improvements
// @description:en   Automatically skip ads on YouTube with advanced options and performance improvements
// @description:vi   Tự động bỏ qua quảng cáo trên YouTube với các tùy chọn nâng cao và cải thiện hiệu suất
// @description:zh-cn 在 YouTube 上自动跳过广告,提供高级选项和性能改进
// @description:zh-tw 在 YouTube 上自動跳過廣告,提供進階選項和效能改進
// @description:ja   高度なオプションとパフォーマンス向上を備えた YouTube の広告を自動的にスキップ
// @description:ko   고급 옵션 및 성능 개선으로 YouTube 광고를 자동으로 건너뛰기
// @description:es   Salta automáticamente los anuncios en YouTube con opciones avanzadas y mejoras de rendimiento
// @description:ru   Автоматически пропускает рекламу на YouTube с расширенными настройками и улучшенной производительностью
// @description:id   Lewati iklan secara otomatis di YouTube dengan opsi lanjutan dan peningkatan kinerja
// @description:hi   उन्नत विकल्पों और प्रदर्शन सुधारों के साथ YouTube पर विज्ञापनों को स्वचालित रूप से छोड़ें
// @author           Jann
// @icon             https://www.google.com/s2/favicons?domain=youtube.com
// @license          MIT
// @match            https://*.youtube.com/*
// @grant            GM_setValue
// @grant            GM_getValue
// @grant            GM_registerMenuCommand
// @grant            GM_addStyle
// ==/UserScript==

(function () {
  'use strict';

  const DEFAULT_CONFIG = {
    skipInterval: 500,
    observerThrottle: 1000,
    muteAds: false, // Leave it as the default false. I recommend keeping it false because setting it to true, while muting ads, can also cause the video's audio to be muted as a side effect.
    hideAdOverlays: true,
    removeAdSlots: true,
    autoHideAnnotations: true,
    disableAutoplay: false,
    improvePerformance: true
  };

  let config = { ...DEFAULT_CONFIG, ...GM_getValue('AdSkipperConfig', {}) };

  function saveConfig() {
    GM_setValue('AdSkipperConfig', config);
  }

  function createSettingsMenu() {
    GM_registerMenuCommand("Configure Ad Skipper", () => {
      const newConfig = prompt("Enter new configuration (JSON):", JSON.stringify(config, null, 2));
      if (newConfig) {
        try {
          config = { ...DEFAULT_CONFIG, ...JSON.parse(newConfig) };
          saveConfig();
          alert("Configuration updated successfully!");
          location.reload();
        } catch (e) {
          alert("Error: Invalid configuration format!");
        }
      }
    });
  }

  function skipAds() {
    const video = document.querySelector('video');
    if (document.querySelector('.ad-showing') && video) {
      video.currentTime = video.duration;
      if (config.muteAds) video.muted = true;
    }

    document.querySelectorAll('.ytp-ad-skip-button, .ytp-ad-skip-button-modern').forEach(button => button.click());

    if (config.hideAdOverlays) {
      const closeBanner = document.querySelector('.ytp-ad-overlay-close-button');
      if (closeBanner) closeBanner.click();
    }

    if (config.removeAdSlots) {
      document.querySelectorAll('ytd-ad-slot-renderer, ytm-promoted-video-renderer').forEach(slot => {
        slot.style.display = 'none';
      });
    }

    if (config.autoHideAnnotations) {
      const annotationToggle = document.querySelector('.ytp-ce-covering-overlay');
      if (annotationToggle) annotationToggle.style.display = 'none';
    }

    if (config.disableAutoplay) {
      const autoplayToggle = document.querySelector('.ytp-autonav-toggle-button[aria-checked="true"]');
      if (autoplayToggle) autoplayToggle.click();
    }
  }

  function throttle(func, limit) {
    let lastFunc;
    let lastRan;
    return function() {
      const context = this;
      const args = arguments;
      if (!lastRan) {
        func.apply(context, args);
        lastRan = Date.now();
      } else {
        clearTimeout(lastFunc);
        lastFunc = setTimeout(function() {
          if ((Date.now() - lastRan) >= limit) {
            func.apply(context, args);
            lastRan = Date.now();
          }
        }, limit - (Date.now() - lastRan));
      }
    }
  }

  const throttledSkipAds = throttle(skipAds, config.observerThrottle);

  const observer = new MutationObserver(throttledSkipAds);

  observer.observe(document.body, {
    childList: true,
    subtree: true
  });

  setInterval(skipAds, config.skipInterval);

  if (config.improvePerformance) {
    GM_addStyle(`
      .ytd-watch-flexy:not([theater]) #secondary.ytd-watch-flexy,
      ytd-watch-next-secondary-results-renderer {
        display: none !important;
      }
    `);
  }

  createSettingsMenu();
})();