// ==UserScript==
// @name YouTube Ad Skipper
// @name:en YouTube Ad Skipper
// @name:vi YouTube Ad Skipper
// @name:zh-cn YouTube 广告跳过器
// @name:zh-tw YouTube 廣告跳過器
// @name:ja YouTube 広告スキッパー
// @name:ko YouTube 광고 건너뛰기
// @name:es YouTube Ad Skipper
// @name:ru Пропускатель рекламы YouTube
// @name:id YouTube Ad Skipper
// @name:hi YouTube विज्ञापन स्किपर
// @namespace http://tampermonkey.net/
// @version 2.2.5
// @description Automatically skip ads on YouTube with advanced options, performance improvements, and best video quality selection.
// @description:en Automatically skip ads on YouTube with advanced options, performance improvements, and best video quality selection.
// @description:vi Tự động bỏ qua quảng cáo trên YouTube với các tùy chọn nâng cao, cải thiện hiệu suất và lựa chọn chất lượng video tốt nhất.
// @description:zh-cn 自动跳过 YouTube 上的广告,提供高级选项、性能改进和最佳视频质量选择。
// @description:zh-tw 自動跳過 YouTube 上的廣告,提供進階選項、效能改進和最佳影片品質選擇。
// @description:ja YouTube の広告を自動的にスキップし、高度なオプション、パフォーマンスの向上、最高のビデオ品質の選択を提供します。
// @description:ko YouTube에서 광고를 자동으로 건너뛰고 고급 옵션, 성능 향상 및 최상의 비디오 품질 선택을 제공합니다。
// @description:es Omite automáticamente los anuncios en YouTube con opciones avanzadas, mejoras de rendimiento y selección de la mejor calidad de video.
// @description:ru Автоматически пропускает рекламу на YouTube с расширенными настройками, улучшением производительности и выбором наилучшего качества видео.
// @description:id Lewati iklan secara otomatis di YouTube dengan opsi lanjutan, peningkatan kinerja, dan pemilihan kualitas video terbaik.
// @description:hi YouTube पर विज्ञापनों को स्वचालित रूप से छोड़ें, उन्नत विकल्पों, प्रदर्शन में सुधार और सर्वोत्तम वीडियो गुणवत्ता चयन के साथ।
// @author Jann
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @match https://*.youtube.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
const DEFAULT_CONFIG = {
skipInterval: 250,
observerThrottle: 500,
muteAds: false,
hideAdOverlays: true,
removeAdSlots: true,
autoHideAnnotations: true,
disableAutoplay: false,
improvePerformance: true,
autoSelectBestQuality: true,
performance: {
hideComments: true,
hideSidebar: true,
disableAnimations: true,
lazyLoadImages: true,
reduceScriptExecution: 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');
// Improved ad detection - More selectors and checks
const adIndicators = [
'.ytp-ad-skip-button',
'.ytp-ad-skip-button-modern',
'.ad-showing',
'.ytp-ad-overlay-close-button',
'.ytp-ad-overlay-image',
'ytd-ad-slot-renderer',
'ytm-promoted-video-renderer',
'[id^="ad-text"]',
'[id^="ad-image"]',
// Add more potential selectors here
];
let isAdPresent = adIndicators.some(selector => document.querySelector(selector));
// Check for video ad duration
if (video && video.duration > 0 && video.currentTime < video.duration) {
isAdPresent = true;
}
if (isAdPresent) {
// Prioritize clicking the skip button
document.querySelectorAll('.ytp-ad-skip-button, .ytp-ad-skip-button-modern').forEach(button => button.click());
// Less aggressive seeking - Seek a few seconds forward
if (video && document.querySelector('.ad-showing')) {
video.currentTime += 5; // Seek 5 seconds forward
video.muted = config.muteAds;
}
// Hide ad overlays
if (config.hideAdOverlays) {
document.querySelectorAll('.ytp-ad-overlay-close-button').forEach(button => button.click());
document.querySelectorAll('.ytp-ad-overlay-image').forEach(overlay => overlay.style.display = 'none');
}
// Remove ad slots
if (config.removeAdSlots) {
document.querySelectorAll('ytd-ad-slot-renderer, ytm-promoted-video-renderer').forEach(slot => {
slot.style.display = 'none';
});
}
}
// Auto-hide annotations
if (config.autoHideAnnotations) {
document.querySelectorAll('.ytp-ce-covering-overlay').forEach(overlay => overlay.style.display = 'none');
}
// Disable autoplay
if (config.disableAutoplay) {
const autoplayToggle = document.querySelector('.ytp-autonav-toggle-button[aria-checked="true"]');
if (autoplayToggle) autoplayToggle.click();
}
}
const 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
});
function setMaxVideoQuality() {
if (!config.autoSelectBestQuality) return;
const qualityMenu = document.querySelector('.ytp-settings-button');
if (qualityMenu) {
qualityMenu.click();
setTimeout(() => {
const qualitySettings = document.querySelector('.ytp-panel-menu');
if (qualitySettings) {
const qualityOptions = Array.from(qualitySettings.querySelectorAll('.ytp-menuitem'));
const highestQuality = qualityOptions.reduce((highest, current) => {
const resolution = current.textContent.trim().match(/(\d+)p/);
const currentResolution = resolution ? parseInt(resolution[1]) : 0;
const highestResolution = highest.textContent.trim().match(/(\d+)p/);
return currentResolution > (highestResolution ? parseInt(highestResolution[1]) : 0) ? current : highest;
}, qualityOptions[0]);
if (highestQuality) {
highestQuality.click();
}
}
qualityMenu.click(); // Close the menu
}, 100);
}
}
function applyPerformanceImprovements() {
if (!config.improvePerformance) return;
const styles = `
${config.performance.hideSidebar ? `
.ytd-watch-flexy:not([theater]) #secondary.ytd-watch-flexy,
ytd-watch-next-secondary-results-renderer {
display: none !important;
}
` : ''}
${config.performance.hideComments ? `
#comments {
display: none !important;
}
` : ''}
${config.performance.disableAnimations ? `
* {
transition: none !important;
animation: none !important;
}
` : ''}
${config.performance.reduceScriptExecution ? `
.ytp-ce-element {
display: none !important;
}
` : ''}
`;
GM_addStyle(styles);
if (config.performance.lazyLoadImages) {
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('img').forEach(img => {
img.loading = 'lazy';
});
});
}
if (config.performance.reduceScriptExecution) {
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
// Handle scroll event here
ticking = false;
});
ticking = true;
}
});
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
// Handle resize event here
}, 250);
});
}
}
function init() {
setInterval(skipAds, config.skipInterval);
setInterval(setMaxVideoQuality, 5000);
applyPerformanceImprovements();
createSettingsMenu();
}
init();
})();