您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动跳过广告、16x倍速、静音、AI选择器更新、防止播放列表误跳、兼容 Video Speed Controller 快捷键,完全本地运行、无UI。
// ==UserScript== // @name YouTube AI广告增强 v2.2.0 (修复播放列表跳片+兼容快捷键) // @namespace http://tampermonkey.net/ // @version 2.2.0 // @description 自动跳过广告、16x倍速、静音、AI选择器更新、防止播放列表误跳、兼容 Video Speed Controller 快捷键,完全本地运行、无UI。 // @author little fool // @match *://www.youtube.com/* // @match *://m.youtube.com/* // @match *://music.youtube.com/* // @match *://www.youtube-nocookie.com/* // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @connect openkey.cloud // @run-at document-end // ==/UserScript== (function () { 'use strict'; const API_URL = 'https://openkey.cloud/v1/chat/completions'; const API_KEY = ['sk-', '1ytLN', 'fSpk5R34n', 'jTF628665', '6331c426cAeCb95E266F8D377'].join(''); const CACHE_KEY = 'yt_ad_selectors_cache'; const HISTORY_KEY = 'yt_ad_selectors_history'; const UPDATE_KEY = 'yt_ad_last_update'; const BASE_SELECTORS = new Set([ '.ytp-ad-module', '.ytp-ad-overlay-container', '.ytp-ad-player-overlay', '.ad-showing .video-ads', '#player-ads' ]); let dynamicSelectors = new Set(); let lastUpdate = 0; let wasAdPlaying = false; let previousMuted = null; let refreshAttempts = 0; let adConfirmed = false; let adCheckTimeout = null; let userModifiedSpeed = false; const MAX_REFRESH_ATTEMPTS = 5; const REFRESH_INTERVAL = 5000; const UPDATE_INTERVAL = 3600000; const log = (...args) => console.log('[YT净化 v2.2.0]', ...args); const getVideo = () => document.querySelector('video'); const isVideoPage = () => /\/watch|\/tv|\/embed/.test(location.pathname); const isHomePage = () => location.pathname === '/'; const safeRun = (fn, desc = '') => { try { fn(); } catch (e) { log(`❌ [${desc}]`, e); } }; async function updateSelectorsViaAI() { if (Date.now() - lastUpdate < UPDATE_INTERVAL) return; try { const res = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'POST', url: API_URL, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${API_KEY}` }, data: JSON.stringify({ model: 'gpt-4o', messages: [{ role: 'user', content: "请提供当前YouTube最新广告CSS选择器数组,仅返回JSON格式的数组。" }], temperature: 0.2 }), onload: resolve, onerror: reject }); }); let result = JSON.parse(res.responseText); const content = result.choices?.[0]?.message?.content?.trim().replace(/```json|```/g, ''); const selectors = JSON.parse(content); if (Array.isArray(selectors) && selectors.length > 0) { dynamicSelectors = new Set(selectors); GM_setValue(CACHE_KEY, [...dynamicSelectors]); GM_setValue(UPDATE_KEY, Date.now()); lastUpdate = Date.now(); const history = GM_getValue(HISTORY_KEY, []); GM_setValue(HISTORY_KEY, [selectors, ...history.slice(0, 9)]); log('✅ [AI更新成功]', selectors); } else throw new Error('选择器格式不正确'); } catch (err) { const history = GM_getValue(HISTORY_KEY, []); dynamicSelectors = new Set(history[0] || []); log('⚠️ 使用缓存选择器', [...dynamicSelectors]); } } function hideAds() { const allSelectors = [...BASE_SELECTORS, ...dynamicSelectors]; allSelectors.forEach(sel => { document.querySelectorAll(sel).forEach(el => { Object.assign(el.style, { display: 'none', opacity: '0.01', pointerEvents: 'none' }); }); }); } function clickSkipButton() { const btn = document.querySelector('.ytp-ad-skip-button'); if (btn && btn.offsetParent !== null) btn.click(); } function accelerateAdPlayback() { const video = getVideo(); if (!video || userModifiedSpeed) return; const adElement = document.querySelector('.ad-showing'); if (adElement && video.currentTime > 1.5) { if (!adConfirmed) { clearTimeout(adCheckTimeout); adCheckTimeout = setTimeout(() => { adConfirmed = true; applyAdAcceleration(video); }, 500); // 延迟判断广告 } else { applyAdAcceleration(video); } } else { adConfirmed = false; clearTimeout(adCheckTimeout); if (!userModifiedSpeed && video.playbackRate !== 1) video.playbackRate = 1; if (wasAdPlaying && previousMuted !== null) { video.muted = previousMuted; previousMuted = null; } } wasAdPlaying = !!adElement; } function applyAdAcceleration(video) { if (video.playbackRate !== 16) { video.playbackRate = 16; previousMuted = video.muted; video.muted = true; log('🎬 广告中:静音 + 加速'); } } function removeAdSubtitles() { const keywords = ['广告', '贊助', '推广', 'Sponsored', 'Sponsor']; document.querySelectorAll('.ytp-caption-segment').forEach(el => { if (keywords.some(k => el.textContent.includes(k))) el.remove(); }); } function detectAdBlackScreen() { const video = getVideo(); const stuck = document.querySelector('.ad-showing') && video && video.readyState >= 2 && video.videoWidth === 0; if (stuck) showTip('yt-black-tip', '⏳ 正在处理卡住的广告...'); else removeTip('yt-black-tip'); } function detectAdBlockWarning() { const signs = [ '广告拦截器', 'adblock', '关闭广告拦截', '广告支持我们的服务', 'Ad blockers violate YouTube’s Terms' ]; return signs.some(k => document.body.innerText.includes(k)); } function showTip(id, msg) { if (document.getElementById(id)) return; const div = document.createElement('div'); div.id = id; div.innerText = msg; Object.assign(div.style, { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', backgroundColor: '#c00', color: '#fff', padding: '10px 16px', fontSize: '14px', fontWeight: 'bold', borderRadius: '6px', zIndex: 9999 }); document.body.appendChild(div); } function removeTip(id) { const el = document.getElementById(id); if (el) el.remove(); } function hideHomepageAds() { const keywords = ['广告', '推广', '赞助', 'Sponsored']; document.querySelectorAll('ytd-rich-item-renderer,ytd-video-renderer').forEach(el => { if (keywords.some(k => el.innerText.includes(k))) el.style.display = 'none'; }); } function observePage() { const observer = new MutationObserver(() => { safeRun(hideAds, '隐藏广告'); safeRun(clickSkipButton, '跳过广告'); safeRun(accelerateAdPlayback, '倍速广告'); safeRun(removeAdSubtitles, '隐藏字幕'); }); observer.observe(document.body, { childList: true, subtree: true }); } function init() { dynamicSelectors = new Set(GM_getValue(CACHE_KEY, [])); lastUpdate = GM_getValue(UPDATE_KEY, 0); updateSelectorsViaAI(); setInterval(updateSelectorsViaAI, UPDATE_INTERVAL); if (isVideoPage()) { observePage(); setInterval(() => safeRun(detectAdBlackScreen, '黑屏检测'), 1000); setInterval(() => { if (detectAdBlockWarning()) { if (refreshAttempts++ < MAX_REFRESH_ATTEMPTS) { showTip('yt-refresh', `⚠️ 检测广告拦截提示,正在刷新...(${refreshAttempts})`); setTimeout(() => location.reload(), 500); } else removeTip('yt-refresh'); } else { removeTip('yt-refresh'); } }, REFRESH_INTERVAL); } if (isHomePage()) { setInterval(() => safeRun(hideHomepageAds, '隐藏首页广告'), 2000); } } // 🔧 检测用户是否用快捷键调整播放速度(如 D/S) document.addEventListener('keydown', (e) => { if (['d', 's', 'D', 'S'].includes(e.key)) { userModifiedSpeed = true; log('🎛️ 快捷键触发:用户已手动调节播放速度,脚本不再控制播放倍速'); } }); init(); })();