WheelSeek — マウスホイールで動画巻き戻し・早送り

マウスホイールであらゆるHTML5動画を巻き戻し・早送り。YouTube、Twitch、全サイト対応。プレーヤー上でのみ有効。

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         WheelSeek — Mouse Wheel Video Rewind
// @name:en      WheelSeek — Mouse Wheel Video Rewind
// @name:ru      WheelSeek — Перемотка видео колёсиком мыши
// @name:es      WheelSeek — Rebobinar vídeo con la rueda del ratón
// @name:fr      WheelSeek — Rembobiner la vidéo avec la molette
// @name:de      WheelSeek — Video zurückspulen mit dem Mausrad
// @name:it      WheelSeek — Riavvolgi video con la rotellina del mouse
// @name:pt-BR   WheelSeek — Rebobinar vídeo com a roda do mouse
// @name:nl      WheelSeek — Video terugspoelen met het scrollwiel
// @name:pl      WheelSeek — Przewijanie wideo kółkiem myszy
// @name:sv      WheelSeek — Spola video med mushjulet
// @name:da      WheelSeek — Spol video med musehjulet
// @name:no      WheelSeek — Spol video med musehjulet
// @name:fi      WheelSeek — Kelaa videota hiiren rullalla
// @name:cs      WheelSeek — Přetáčení videa kolečkem myši
// @name:sk      WheelSeek — Pretáčanie videa kolieskom myši
// @name:hu      WheelSeek — Videó visszatekerése az egérgörgővel
// @name:ro      WheelSeek — Derulare video cu rotița mouse-ului
// @name:be      WheelSeek — Перамотка відэа колцам мышы
// @name:bg      WheelSeek — Превъртане на видео с колелцето на мишката
// @name:el      WheelSeek — Επαναφορά βίντεο με τον τροχό του ποντικιού
// @name:sr      WheelSeek — Премотавање видеа точкићем миша
// @name:hr      WheelSeek — Premotavanje videa kotačićem miša
// @name:sl      WheelSeek — Previjanje videa s koleščkom miške
// @name:lt      WheelSeek — Vaizdo įrašo persukimas pelės ratuku
// @name:lv      WheelSeek — Video pārtīšana ar peles ritenīti
// @name:uk      WheelSeek — Перемотка відео коліщатком миші
// @name:tr      WheelSeek — Fare tekerleğiyle video geri sarma
// @name:ar      WheelSeek — إرجاع الفيديو بعجلة الماوس
// @name:fa      WheelSeek — بازگردانی ویدیو با چرخ ماوس
// @name:he      WheelSeek — הרצה אחורה של וידאו בגלגלת העכבר
// @name:hi      WheelSeek — माउस व्हील से वीडियो रिवाइंड
// @name:bn      WheelSeek — মাউস হুইল দিয়ে ভিডিও রিওয়াইন্ড
// @name:te      WheelSeek — మౌస్ వీల్‌తో వీడియో రివైండ్
// @name:ta      WheelSeek — மவுஸ் வீலால் வீடியோ ரிவைண்ட்
// @name:mr      WheelSeek — माउस व्हीलने व्हिडिओ रिवाइंड
// @name:zh-CN   WheelSeek — 鼠标滚轮快进快退视频
// @name:zh-TW   WheelSeek — 滑鼠滾輪快轉倒轉影片
// @name:zh-HK   WheelSeek — 滑鼠滾輪快轉倒轉影片
// @name:ja      WheelSeek — マウスホイールで動画巻き戻し・早送り
// @name:ko      WheelSeek — 마우스 휠로 동영상 되감기
// @name:th      WheelSeek — กรอวิดีโอด้วยล้อเมาส์
// @name:vi      WheelSeek — Tua video bằng con lăn chuột
// @name:id      WheelSeek — Putar ulang video dengan roda mouse
// @name:ms      WheelSeek — Gulung video dengan roda tetikus
// @name:tl      WheelSeek — I-rewind ang video gamit ang mouse wheel
// @name:my      WheelSeek — မောက်စ်ဘီးဖြင့် ဗီဒီယိုပြန်ရစ်ရန်
// @name:sw      WheelSeek — Rudisha video kwa gurudumu la panya
// @name:am      WheelSeek — ቪዲዮን በማውስ ጎማ ማጠንጠን
// @name:ha      WheelSeek — Sake juyawa bidiyo da wheel na kwamfuta
// @name:ur      WheelSeek — ماؤس وہیل سے ویڈیو ریوائنڈ
// @name:ca      WheelSeek — Rebobina el vídeo amb la roda del ratolí
// @name:zu      WheelSeek — Buyisela ividiyo ngesondo legundane
// @name:yue     WheelSeek — 滑鼠滾輪快轉倒轉影片
// @name:es-419  WheelSeek — Rebobinar video con la rueda del ratón
// @namespace    https://github.com/GScripKa
// @version      0.39
// @description         Rewind & fast-forward any HTML5 video with the mouse wheel. YouTube, Twitch & all sites. Cursor-aware: only activates over the video player.
// @description:en      Rewind & fast-forward any HTML5 video with the mouse wheel. YouTube, Twitch & all sites. Cursor-aware: only activates over the video player.
// @description:ru      Перемотка любого HTML5 видео колёсиком мыши. YouTube, Twitch и все сайты. Работает только когда курсор на видео.
// @description:es      Rebobina y avanza cualquier vídeo HTML5 con la rueda del ratón. YouTube, Twitch y todos los sitios. Solo se activa sobre el reproductor.
// @description:fr      Rembobinez et avancez rapidement toute vidéo HTML5 avec la molette de la souris. YouTube, Twitch et tous les sites. Ne s'active que sur le lecteur.
// @description:de      Vor- und Zurückspulen jedes HTML5-Videos mit dem Mausrad. YouTube, Twitch und alle Websites. Aktiviert sich nur über dem Player.
// @description:it      Riavvolgi e avanza qualsiasi video HTML5 con la rotellina del mouse. YouTube, Twitch e tutti i siti. Si attiva solo sul lettore video.
// @description:pt-BR   Rebobine e avance qualquer vídeo HTML5 com a roda do mouse. YouTube, Twitch e todos os sites. Ativa-se apenas sobre o player.
// @description:nl      Terug- en vooruitspoelen van elke HTML5-video met het scrollwiel. YouTube, Twitch en alle sites. Activeert alleen boven de speler.
// @description:pl      Przewijaj dowolne wideo HTML5 kółkiem myszy. YouTube, Twitch i wszystkie strony. Aktywuje się tylko nad odtwarzaczem.
// @description:sv      Spola tillbaka och framåt i alla HTML5-videor med mushjulet. YouTube, Twitch och alla sajter. Aktiveras bara över spelaren.
// @description:da      Spol tilbage og frem i enhver HTML5-video med musehjulet. YouTube, Twitch og alle sider. Aktiveres kun over afspilleren.
// @description:no      Spol tilbake og fremover i enhver HTML5-video med musehjulet. YouTube, Twitch og alle nettsteder. Aktiveres kun over spilleren.
// @description:fi      Kelaa taaksepäin ja eteenpäin mitä tahansa HTML5-videota hiiren rullalla. YouTube, Twitch ja kaikki sivustot. Aktivoituu vain soittimen päällä.
// @description:cs      Přetáčejte jakékoli HTML5 video kolečkem myši. YouTube, Twitch a všechny weby. Aktivuje se pouze nad přehrávačem.
// @description:sk      Pretáčajte akékoľvek HTML5 video kolieskom myši. YouTube, Twitch a všetky weby. Aktivuje sa len nad prehrávačom.
// @description:hu      Tekerjen vissza és előre bármilyen HTML5-videóban az egérgörgővel. YouTube, Twitch és minden webhely. Csak a lejátszó felett aktiválódik.
// @description:ro      Derulați înainte și înapoi orice video HTML5 cu rotița mouse-ului. YouTube, Twitch și toate site-urile. Se activează doar peste player.
// @description:be      Перамоткa любога HTML5 відэа колцам мышы. YouTube, Twitch і ўсе сайты. Працуе толькі калі курсор на відэа.
// @description:bg      Превъртане назад и напред на всяко HTML5 видео с колелцето на мишката. YouTube, Twitch и всички сайтове. Активира се само върху плеъра.
// @description:el      Επαναφορά και γρήγορη προώθηση οποιουδήποτε βίντεο HTML5 με τον τροχό του ποντικιού. YouTube, Twitch και όλες οι ιστοσελίδες.
// @description:sr      Премотавајте уназад и унапред било који HTML5 видео точкићем миша. YouTube, Twitch и сви сајтови. Активира се само изнад плејера.
// @description:hr      Premotavajte unaprijed i unatrag bilo koji HTML5 video kotačićem miša. YouTube, Twitch i sve stranice. Aktivira se samo iznad playera.
// @description:sl      Previjajte nazaj in naprej katerikoli HTML5 video s koleščkom miške. YouTube, Twitch in vse spletne strani. Aktivira se samo nad predvajalnikom.
// @description:lt      Persukite atgal ir pirmyn bet kurį HTML5 vaizdo įrašą pelės ratuku. YouTube, Twitch ir visos svetainės. Aktyvuojama tik virš grotuvo.
// @description:lv      Pārtiniet uz priekšu un atpakaļ jebkuru HTML5 video ar peles ritenīti. YouTube, Twitch un visas vietnes. Aktivizējas tikai virs atskaņotāja.
// @description:uk      Перемотка будь-якого HTML5 відео коліщатком миші. YouTube, Twitch та всі сайти. Працює лише коли курсор на відео.
// @description:tr      Herhangi bir HTML5 videoyu fare tekerleğiyle ileri ve geri sarın. YouTube, Twitch ve tüm siteler. Yalnızca oynatıcı üzerinde etkinleşir.
// @description:ar      إرجاع وتقديم أي فيديو HTML5 بعجلة الماوس. يوتيوب، تويتش وجميع المواقع. يعمل فقط فوق مشغل الفيديو.
// @description:fa      هر ویدیوی HTML5 را با چرخ ماوس جلو و عقب ببرید. یوتیوب، توییچ و همه سایت‌ها. فقط روی پخش‌کننده فعال می‌شود.
// @description:he      הרצה קדימה ואחורה של כל סרטון HTML5 עם גלגלת העכבר. YouTube, Twitch וכל האתרים. פועל רק מעל הנגן.
// @description:hi      माउस व्हील से किसी भी HTML5 वीडियो को रिवाइंड और फास्ट-फॉरवर्ड करें। YouTube, Twitch और सभी साइटें। केवल प्लेयर पर सक्रिय होता है।
// @description:bn      মাউস হুইল দিয়ে যেকোনো HTML5 ভিডিও রিওয়াইন্ড ও ফাস্ট-ফরওয়ার্ড করুন। YouTube, Twitch এবং সমস্ত সাইট। শুধুমাত্র প্লেয়ারের উপর সক্রিয় হয়।
// @description:te      మౌస్ వీల్‌తో ఏదైనా HTML5 వీడియోను రివైండ్ మరియు ఫాస్ట్-ఫార్వర్డ్ చేయండి. YouTube, Twitch మరియు అన్ని సైట్‌లు. ప్లేయర్ పై మాత్రమే సక్రియం అవుతుంది.
// @description:ta      மவுஸ் வீலால் எந்த HTML5 வீடியோவையும் ரிவைண்ட் மற்றும் ஃபாஸ்ட்-ஃபார்வர்ட் செய்யுங்கள். YouTube, Twitch மற்றும் அனைத்து தளங்கள். பிளேயர் மீது மட்டுமே செயல்படும்.
// @description:mr      माउस व्हीलने कोणताही HTML5 व्हिडिओ रिवाइंड आणि फास्ट-फॉरवर्ड करा. YouTube, Twitch आणि सर्व साइट्स. फक्त प्लेयरवर सक्रिय होतो.
// @description:zh-CN   用鼠标滚轮快进快退任何HTML5视频。支持YouTube、Twitch及所有网站。仅在视频播放器上激活。
// @description:zh-TW   用滑鼠滾輪快轉倒轉任何HTML5影片。支援YouTube、Twitch及所有網站。僅在影片播放器上啟用。
// @description:zh-HK   用滑鼠滾輪快轉倒轉任何HTML5影片。支援YouTube、Twitch及所有網站。僅在影片播放器上啟用。
// @description:ja      マウスホイールであらゆるHTML5動画を巻き戻し・早送り。YouTube、Twitch、全サイト対応。プレーヤー上でのみ有効。
// @description:ko      마우스 휠로 모든 HTML5 동영상을 되감기 및 빨리감기. YouTube, Twitch 및 모든 사이트. 플레이어 위에서만 활성화됩니다.
// @description:th      กรอวิดีโอ HTML5 ทั้งหมดด้วยล้อเมาส์ YouTube, Twitch และทุกเว็บไซต์ ใช้งานได้เฉพาะบนเครื่องเล่นวิดีโอ
// @description:vi      Tua lại và tua nhanh bất kỳ video HTML5 nào bằng con lăn chuột. YouTube, Twitch và mọi trang web. Chỉ kích hoạt trên trình phát.
// @description:id      Putar mundur & maju cepat video HTML5 apa pun dengan roda mouse. YouTube, Twitch & semua situs. Hanya aktif di atas pemutar.
// @description:ms      Undur & maju laju mana-mana video HTML5 dengan roda tetikus. YouTube, Twitch & semua laman. Hanya aktif di atas pemain.
// @description:tl      I-rewind at i-fast-forward ang anumang HTML5 video gamit ang mouse wheel. YouTube, Twitch at lahat ng site. Nag-a-activate lang sa ibabaw ng player.
// @description:my      မည်သည့် HTML5 ဗီဒီယိုကိုမဆို မောက်စ်ဘီးဖြင့် ပြန်ရစ်/ရှေ့ဆက်နိုင်ပါသည်။ YouTube, Twitch နှင့် ဝဘ်ဆိုက်အားလုံး။
// @description:sw      Rudisha nyuma na mbele video yoyote ya HTML5 kwa gurudumu la panya. YouTube, Twitch na tovuti zote. Inafanya kazi tu juu ya kichezaji.
// @description:am      ማንኛውንም HTML5 ቪዲዮ በማውስ ጎማ ወደ ኋላ እና ወደ ፊት ያሽከርክሩ። YouTube, Twitch እና ሁሉም ድረ-ገጾች።
// @description:ha      Sake juyawa da kuma ci gaba da sauri akan kowane bidiyo na HTML5 ta amfani da wheel na linzami. YouTube, Twitch da dukkan shafukan yanar gizo.
// @description:ur      ماؤس وہیل سے کسی بھی HTML5 ویڈیو کو ریوائنڈ اور فاسٹ فارورڈ کریں۔ YouTube، Twitch اور تمام سائٹس۔ صرف پلیئر پر فعال ہوتا ہے۔
// @description:ca      Rebobina i avança qualsevol vídeo HTML5 amb la roda del ratolí. YouTube, Twitch i tots els llocs web. Només s'activa sobre el reproductor.
// @description:zu      Buyisela emuva uphinde uqhubeke ngokushesha noma iyiphi ividiyo ye-HTML5 ngesondo legundane. YouTube, Twitch nazo zonke iziza.
// @description:yue     用滑鼠滾輪快轉倒轉任何HTML5影片。支援YouTube、Twitch及所有網站。僅在影片播放器上啟用。
// @description:es-419  Rebobina y avanza cualquier video HTML5 con la rueda del ratón. YouTube, Twitch y todos los sitios. Solo se activa sobre el reproductor.
// @author       GScripKa
// @match        *://*/*
// @grant        none
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const SEEK_TIME = 5;
    let wheelListenerAdded = false;

    // Селекторы контейнеров видеоплееров
    const PLAYER_SELECTORS = [
        '[data-a-target="video-player"]',
        '.video-player__container',
        '.persistent-player',
        '.html5-video-player',
        '.video-js',
        '.plyr',
        '.jwplayer',
        '.vjs-tech',
        '.player-video',
        '.video-player',
        '.media-player',
        '[data-a-player-type]',
        '.player-root',
        '.theoplayer-container',
        '.flowplayer',
    ];

    // Найти видео, связанное с элементом под курсором
    function findVideoAt(x, y) {
        const elem = document.elementFromPoint(x, y);
        if (!elem) return null;

        // 1. Сам элемент — видео
        if (elem.tagName === 'VIDEO') return elem;

        // 2. Курсор внутри известного контейнера-плеера → видео в этом контейнере
        //    closest() матчит ТОЛЬКО предков elem, т.е. курсор гарантированно внутри
        for (const selector of PLAYER_SELECTORS) {
            try {
                const container = elem.closest(selector);
                if (container) {
                    const video = container.querySelector('video');
                    if (video) return video;
                }
            } catch (e) { /* невалидный селектор */ }
        }

        // 3. Геометрическая проверка: курсор попадает в bounding rect видео
        //    Не ходим по DOM вверх — это вызывало ложные срабатывания
        const videos = document.querySelectorAll('video');
        for (const v of videos) {
            const rect = v.getBoundingClientRect();
            if (rect.width < 200 || rect.height < 150) continue;
            if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
                return v;
            }
        }

        return null;
    }

    // Проверка: действительно интерактивный элемент формы
    function isInteractive(elem) {
        if (!elem) return false;
        const tag = elem.tagName;
        if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;
        if (elem.isContentEditable) return true;
        return false;
    }

    // Проверка: есть ли скроллируемый НЕ-плеерный элемент между курсором и видео
    // Останавливается на границе контейнера плеера
    function isOnScrollableNonPlayer(elem, video) {
        let el = elem;
        while (el && el !== document.documentElement) {
            // Дошли до видео — мы в плеере
            if (el === video) return false;
            if (el.tagName === 'VIDEO') return false;

            // Дошли до общего предка, содержащего видео — мы в плеере
            if (el.contains && el.contains(video)) return false;

            // Дошли до известного контейнера плеера — мы в плеере
            for (const selector of PLAYER_SELECTORS) {
                try { if (el.matches(selector)) return false; } catch(e) {}
            }

            // Нашли скроллируемый элемент ДО плеера — не перехватываем
            try {
                const style = window.getComputedStyle(el);
                if (
                    (style.overflowY === 'auto' || style.overflowY === 'scroll') &&
                    el.scrollHeight > el.clientHeight
                ) {
                    return true;
                }
            } catch(e) {}

            el = el.parentElement;
        }
        return false;
    }

    // Обработчик колёсика мыши
    function handleWheel(e) {
        // Быстрый выход: нет видео на странице
        if (!document.querySelector('video')) return;

        const elem = document.elementFromPoint(e.clientX, e.clientY);
        if (!elem) return;

        // Не перехватываем на элементах форм
        if (isInteractive(elem)) return;

        // Сначала находим видео — без видео нет смысла проверять дальше
        const video = findVideoAt(e.clientX, e.clientY);
        if (!video) return;
        if (!video.duration || video.duration === Infinity) return; // live-стримы

        // Проверяем размер видео
        const rect = video.getBoundingClientRect();
        if (rect.width < 200 || rect.height < 150) return;

        // Проверяем: есть ли скроллируемый элемент между курсором и плеером
        if (isOnScrollableNonPlayer(elem, video)) return;

        e.preventDefault();
        e.stopPropagation();

        if (e.deltaY > 0) {
            video.currentTime = Math.max(0, video.currentTime - SEEK_TIME);
        } else {
            video.currentTime = Math.min(video.duration, video.currentTime + SEEK_TIME);
        }

        showOverlay(e.deltaY > 0 ? -SEEK_TIME : SEEK_TIME);
    }

    // Визуальный overlay
    function showOverlay(seconds) {
        let overlay = document.getElementById('__wheel_seek_overlay');
        if (!overlay) {
            overlay = document.createElement('div');
            overlay.id = '__wheel_seek_overlay';
            overlay.style.cssText = `
                position: fixed; top: 50%; left: 50%;
                transform: translate(-50%, -50%);
                background: rgba(0,0,0,0.8); color: #fff;
                padding: 10px 24px; border-radius: 8px;
                font-size: 28px; font-family: sans-serif; font-weight: bold;
                z-index: 2147483647; pointer-events: none;
                transition: opacity 0.3s;
            `;
            document.body.appendChild(overlay);
        }

        overlay.textContent = (seconds > 0 ? '+' : '') + seconds + 's';
        overlay.style.opacity = '1';

        clearTimeout(overlay._hideTimer);
        overlay._hideTimer = setTimeout(() => {
            overlay.style.opacity = '0';
        }, 600);
    }

    // Инициализация
    function init() {
        if (wheelListenerAdded) return;
        wheelListenerAdded = true;
        document.addEventListener('wheel', handleWheel, { passive: false, capture: true });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

})();