Greasy Fork is available in English.

Video Background Play Fix2

Prevents YouTube and Vimeo from pausing videos when minimizing or switching tabs. Cross-browser port of https://addons.mozilla.org/en-US/firefox/addon/video-background-play-fix/

  1. /* ==UserStyle==
  2. @name Video Background Play Fix2
  3. @namespace https://greatest.deepsurf.us/en/users/xxoo110
  4. @version 20250423
  5. @description Prevents YouTube and Vimeo from pausing videos when minimizing or switching tabs. Cross-browser port of https://addons.mozilla.org/en-US/firefox/addon/video-background-play-fix/
  6. @author xxoo110
  7. @match *://*.youtube.com/*
  8. @match *://*.vimeo.com/*
  9. @grant none
  10. @run-at document-start
  11. @background
  12. @license MIT
  13. ==/UserStyle== */
  14.  
  15. (function () {
  16. 'use strict';
  17.  
  18. const IS_YOUTUBE = window.location.hostname.search(/(?:^|.+\.)youtube\.com/) > -1 ||
  19. window.location.hostname.search(/(?:^|.+\.)youtube-nocookie\.com/) > -1;
  20. const IS_MOBILE_YOUTUBE = window.location.hostname == 'm.youtube.com';
  21. const IS_DESKTOP_YOUTUBE = IS_YOUTUBE && !IS_MOBILE_YOUTUBE;
  22. const IS_VIMEO = window.location.hostname.search(/(?:^|.+\.)vimeo\.com/) > -1;
  23.  
  24. const IS_ANDROID = window.navigator.userAgent.indexOf('Android') > -1;
  25.  
  26. // Page Visibility API
  27. if (IS_ANDROID || !IS_DESKTOP_YOUTUBE) {
  28. Object.defineProperties(document,
  29. { 'hidden': { value: false }, 'visibilityState': { value: 'visible' } });
  30. }
  31.  
  32. window.addEventListener(
  33. 'visibilitychange', evt => evt.stopImmediatePropagation(), true);
  34.  
  35. // Fullscreen API
  36. if (IS_VIMEO) {
  37. window.addEventListener(
  38. 'fullscreenchange', evt => evt.stopImmediatePropagation(), true);
  39. }
  40.  
  41. // User activity tracking
  42. if (IS_YOUTUBE) {
  43. loop(pressKey, 60 * 1000, 10 * 1000); // every minute +/- 10 seconds
  44. }
  45.  
  46. function pressKey() {
  47. const key = 18;
  48. sendKeyEvent("keydown", key);
  49. sendKeyEvent("keyup", key);
  50. }
  51.  
  52. function sendKeyEvent(aEvent, aKey) {
  53. document.dispatchEvent(new KeyboardEvent(aEvent, {
  54. bubbles: true,
  55. cancelable: true,
  56. keyCode: aKey,
  57. which: aKey,
  58. }));
  59. }
  60.  
  61. function loop(aCallback, aDelay, aJitter) {
  62. let jitter = getRandomInt(-aJitter / 2, aJitter / 2);
  63. let delay = Math.max(aDelay + jitter, 0);
  64.  
  65. window.setTimeout(() => {
  66. aCallback();
  67. loop(aCallback, aDelay, aJitter);
  68. }, delay);
  69. }
  70.  
  71. function getRandomInt(aMin, aMax) {
  72. let min = Math.ceil(aMin);
  73. let max = Math.floor(aMax);
  74. return Math.floor(Math.random() * (max - min)) + min;
  75. }
  76.  
  77. })();