Click on video thumbnail to play in MPV

Opens videos in external player (mpv) by simply clicking on a thumbnail.

  1. // ==UserScript==
  2. // @name Click on video thumbnail to play in MPV
  3. // @name:ru Нажми на митиатюру для проигрывания в MPV
  4. // @namespace nsinister.scripts.videothumb2mpv
  5. // @match https://*.youtube.com/*
  6. // @match https://vimeo.com/*
  7. // @grant none
  8. // @version 0.1
  9. // @author nSinister
  10. // @license MIT
  11. // @description Opens videos in external player (mpv) by simply clicking on a thumbnail.
  12. // @description:ru Проигрывает ролики во внешнем плеере (mpv) по нажатию на миниатюру
  13. //
  14. // ==/UserScript==
  15.  
  16. "use strict";
  17.  
  18.  
  19. let observer;
  20. let listeners = [];
  21.  
  22. let sites = {
  23. "youtube.com": { sel: "a.ytd-thumbnail", url: "https://www.youtube.com", needsFullUrl: true },
  24. "vimeo.com": { sel: "a.iris_video-vital__overlay", url: "https://vimeo.com", needsFullUrl: false },
  25. };
  26.  
  27. // Watches for new elements based on selector to appear on page and assigns a function to them
  28. function ready(selector, func) {
  29. listeners.push({ selector: selector, func: func });
  30. if (!observer) {
  31. observer = new MutationObserver(checkDOM);
  32. observer.observe(document.documentElement, { childList: true, subtree: true });
  33. }
  34. checkDOM();
  35. }
  36.  
  37. function checkDOM() {
  38. for (let i = 0, len = listeners.length, listener, elements; i < len; i++) {
  39. listener = listeners[i];
  40. elements = document.querySelectorAll(listener.selector);
  41. for (let j = 0, jlen = elements.length, element; j < jlen; j++) {
  42. element = elements[j];
  43. if (!element.ready) {
  44. element.ready = true;
  45. listener.func.call(element, element);
  46. }
  47. }
  48. }
  49. }
  50.  
  51. // Replaces https:// hyperlinks with mpv:// and overrides click event
  52. function replaceLink(node, site) {
  53. if(node) {
  54. let hrefval = node.getAttribute('href');
  55. if (hrefval == null || hrefval.startsWith("mpv"))
  56. return;
  57. let newval = "mpv://" + btoa( (site.needsFullUrl ? site.url : "") + hrefval);
  58. node.setAttribute('href', newval);
  59. node.addEventListener('click', function(event){
  60. event.preventDefault();
  61. event.stopPropagation();
  62. location.href = newval;
  63. });
  64. }
  65. }
  66.  
  67. // Detects and returns current site from the list of known websites
  68. function detectSite(sites) {
  69. let site;
  70. for (let s in sites) {
  71. site = sites[s];
  72. if (location.href.includes(s)) {
  73. return site;
  74. }
  75. }
  76. return null;
  77. }
  78.  
  79. let site = detectSite(sites)
  80. if (site) {
  81. ready(site.sel, function(element) {
  82. replaceLink(element, site);
  83. });
  84. }