|
// ==UserScript== // @name YouTube Auto Skip & Volume Lower (UI Linked) // @namespace http://tampermonkey.net/ // @version 2.4 // @description YouTubeプレイヤーUIと完全に連動させて広告中の音量を下げ、終了後に復元します // @author You // @match https://www.youtube.com/* // @grant none // @run-at document-end // ==/UserScript==
(function() { 'use strict';
let originalVolume = null; // 元の音量 (0〜100) let isMutedBefore = false; let isSkipping = false;
function getTimestamp() { const now = new Date(); const hrs = String(now.getHours()).padStart(2, '0'); const min = String(now.getMinutes()).padStart(2, '0'); const sec = String(now.getSeconds()).padStart(2, '0'); return `[${hrs}:${min}:${sec}]`; }
// YouTube公式プレイヤー要素を取得 function getMoviePlayer() { return document.getElementById('movie_player') || document.querySelector('.html5-video-player'); }
// 広告中かどうかを判定 function isAdPlaying() { if (document.querySelector('.ytp-ad-info-hover-text-button, .ytp-ad-hover-text-button')) return true; if (document.querySelector('.ytp-ad-badge--clean-player, .ytp-ad-badge-text')) return true; if (document.querySelector('.ytp-ad-player-overlay-layout')) return true; if (document.querySelector('.ytp-skip-ad-button')) return true;
const player = getMoviePlayer(); if (player) { if (player.classList.contains('ad-showing') || player.classList.contains('ad-interrupting')) return true; if (typeof player.getVideoData === 'function') { const data = player.getVideoData(); if (data && (data.isAd === 1 || data.isAd === true || data.ad_id)) return true; } } return false; }
// 音量を適用する(YouTube APIと<video>タグの両方に働きかける) function setPlayerVolume(targetVolumePercent) { const player = getMoviePlayer(); const video = document.querySelector('video');
// 1. YouTube公式API経由でセット(画面のスライダー表示も連動して変わる) if (player && typeof player.setVolume === 'function') { player.setVolume(targetVolumePercent); // 0 〜 100 で指定 }
// 2. DOMのvideo要素にも念のためセット (0.0 〜 1.0) if (video) { video.volume = targetVolumePercent / 100; } }
// 現在の音量を取得 (0〜100) function getPlayerVolume() { const player = getMoviePlayer(); if (player && typeof player.getVolume === 'function') { return player.getVolume(); } const video = document.querySelector('video'); return video ? Math.round(video.volume * 100) : 100; }
function checkAndHandleAd() { const video = document.querySelector('video'); if (!video) return;
const isAd = isAdPlaying();
if (isAd) { // --- 広告検知時 --- if (originalVolume === null) { // 退避処理 originalVolume = getPlayerVolume(); isMutedBefore = video.muted;
// 音量を 10% に変更(UIにも反映) setPlayerVolume(10); console.log(`${getTimestamp()} [AutoSkip] 広告検出:音量を10%に下げました。(元: ${originalVolume}%)`); }
// --- スキップ処理 --- const skipButton = document.querySelector('.ytp-skip-ad-button'); const isButtonActive = skipButton && window.getComputedStyle(skipButton).opacity === '1' && skipButton.innerText.includes('スキップ');
if (isButtonActive && !isSkipping) { if (!document.querySelector('.ytp-ad-player-overlay-layout')) return;
isSkipping = true; const randomDelay = Math.floor(Math.random() * (500 - 100 + 1)) + 100; console.log(`${getTimestamp()} [AutoSkip] スキップ実行準備... (${randomDelay}ms 後)`);
setTimeout*1 { video.currentTime = video.duration; console.log(`${getTimestamp()} [AutoSkip] 広告を終了させました。`); } isSkipping = false; }, randomDelay); }
} else { // --- 通常動画時 --- if (originalVolume !== null) { // 広告が終わったら元の音量に戻す setPlayerVolume(originalVolume); video.muted = isMutedBefore;
console.log(`${getTimestamp()} [AutoSkip] 通常動画を検出:音量を元の ${originalVolume}% に戻しました。`); originalVolume = null; isMutedBefore = false; } } }
setInterval(checkAndHandleAd, 300); })();
|