NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Click on video thumbnail to play in MPV // @namespace nSinister.scripts.videothumb2mpv // @match https://*.youtube.com/* // @match https://vimeo.com/* // @grant none // @version 0.1 // @author nSinister // @license MIT // @updateURL https://github.com/nsinister/videothumb2mpv/edit/master/userscript.js // @downloadURL https://github.com/nsinister/videothumb2mpv/edit/master/userscript.js // @description Open videos in external player (mpv) by simply clicking on a thumbnail. // @copyright 2021, nsinister // // ==/UserScript== (function () { "use strict"; let observer; let listeners = []; let sites = { "youtube.com": { sel: "a.ytd-thumbnail", url: "https://www.youtube.com", needsFullUrl: true }, "vimeo.com": { sel: "a.iris_video-vital__overlay", url: "https://vimeo.com", needsFullUrl: false }, }; // Watches for new elements based on selector to appear on page and assigns a function to them function ready(selector, func) { listeners.push({ selector: selector, func: func }); if (!observer) { observer = new MutationObserver(checkDOM); observer.observe(document.documentElement, { childList: true, subtree: true }); } checkDOM(); } function checkDOM() { for (let i = 0, len = listeners.length, listener, elements; i < len; i++) { listener = listeners[i]; elements = document.querySelectorAll(listener.selector); for (let j = 0, jlen = elements.length, element; j < jlen; j++) { element = elements[j]; if (!element.ready) { element.ready = true; listener.func.call(element, element); } } } } // Replaces https:// hyperlinks with mpv:// and overrides click event function replaceLink(node, site) { if(node) { let hrefval = node.getAttribute('href'); if (hrefval == null || hrefval.startsWith("mpv")) return; let newval = "mpv://" + btoa( (site.needsFullUrl ? site.url : "") + hrefval); node.setAttribute('href', newval); node.addEventListener('click', function(event){ event.preventDefault(); event.stopPropagation(); location.href = newval; }); } } // Detects and returns current site from the list of known websites function detectSite(sites) { let site; for (let s in sites) { site = sites[s]; if (location.href.includes(s)) { return site; } } return null; } let site = detectSite(sites) if (site) { ready(site.sel, function(element) { replaceLink(element, site); }); } }())