Social Media Background Playback

Keeps videos playing in the background on Google, TikTok, & Instagram

  1. // ==UserScript==
  2. // @name Social Media Background Playback
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Keeps videos playing in the background on Google, TikTok, & Instagram
  6. // @author UniverseDev
  7. // @icon https://i.postimg.cc/nhtdDdSF/DALL-E-2025-02-03-08-50-33-A-sleek-and-modern-icon-representing-background-video-playback-The-ico.webp
  8. // @license GPL-3.0-or-later
  9. // @match https://www.google.com/search?*
  10. // @match https://www.tiktok.com/*
  11. // @match https://www.instagram.com/*
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. function overrideVisibility() {
  19. Object.defineProperties(document, {
  20. hidden: {
  21. configurable: true,
  22. get: () => false
  23. },
  24. visibilityState: {
  25. configurable: true,
  26. get: () => 'visible'
  27. }
  28. });
  29. document.dispatchEvent(new Event('visibilitychange'));
  30. console.log("Visibility override activated");
  31. }
  32.  
  33. function restoreVisibility() {
  34. try {
  35. delete document.hidden;
  36. delete document.visibilityState;
  37. console.log("Visibility override deactivated");
  38. } catch (e) {
  39. console.error("Error restoring visibility:", e);
  40. }
  41. }
  42.  
  43. function googleVideoPlayback() {
  44. function keepPageVisible() {
  45. let hiddenProp;
  46. if (typeof document.hidden !== "undefined") {
  47. hiddenProp = "hidden";
  48. } else if (typeof document.msHidden !== "undefined") {
  49. hiddenProp = "msHidden";
  50. } else if (typeof document.webkitHidden !== "undefined") {
  51. hiddenProp = "webkitHidden";
  52. } else {
  53. console.warn('Google: Visibility API not supported');
  54. return;
  55. }
  56. try {
  57. Object.defineProperty(document, hiddenProp, {
  58. get: () => false,
  59. configurable: true
  60. });
  61. Object.defineProperty(document, 'visibilityState', {
  62. get: () => 'visible',
  63. configurable: true
  64. });
  65. console.log('Google: Page visibility override applied');
  66. } catch (error) {
  67. console.error('Google: Failed to override visibility', error);
  68. }
  69. }
  70.  
  71. function checkAndActivateForVideo() {
  72. const videoElements = document.querySelectorAll('video');
  73. if (videoElements.length > 0) {
  74. keepPageVisible();
  75. }
  76. }
  77.  
  78. function checkAndActivateVisibilityOverride() {
  79. const fragment = window.location.hash;
  80. if (fragment.includes('vid:')) {
  81. keepPageVisible();
  82. } else {
  83. console.log('Google: Not a video page based on URL fragment.');
  84. }
  85. }
  86.  
  87. setInterval(checkAndActivateForVideo, 2000);
  88. window.addEventListener('load', () => {
  89. checkAndActivateForVideo();
  90. checkAndActivateVisibilityOverride();
  91. });
  92.  
  93. const originalPushState = history.pushState;
  94. const originalReplaceState = history.replaceState;
  95. history.pushState = function() {
  96. originalPushState.apply(this, arguments);
  97. checkAndActivateForVideo();
  98. checkAndActivateVisibilityOverride();
  99. };
  100. history.replaceState = function() {
  101. originalReplaceState.apply(this, arguments);
  102. checkAndActivateForVideo();
  103. checkAndActivateVisibilityOverride();
  104. };
  105.  
  106. checkAndActivateForVideo();
  107. checkAndActivateVisibilityOverride();
  108. }
  109.  
  110. function socialVideoPlayback(platform) {
  111. let isOverrideActive = false;
  112. let isVideoPlaying = false;
  113. let currentVideoElement = null;
  114.  
  115. function activateOverride() {
  116. if (!isOverrideActive) {
  117. overrideVisibility();
  118. isOverrideActive = true;
  119. console.log(platform + ": Background Playback Activated");
  120. }
  121. }
  122.  
  123. function deactivateOverride() {
  124. if (isOverrideActive) {
  125. restoreVisibility();
  126. isOverrideActive = false;
  127. console.log(platform + ": Background Playback Deactivated");
  128. }
  129. }
  130.  
  131. document.addEventListener('play', function(event) {
  132. if (event.target.tagName === 'VIDEO') {
  133. isVideoPlaying = true;
  134. currentVideoElement = event.target;
  135. console.log(platform + ": Video started.");
  136. if (document.hidden) {
  137. activateOverride();
  138. }
  139. }
  140. }, true);
  141.  
  142. document.addEventListener('ended', function(event) {
  143. if (event.target.tagName === 'VIDEO' && event.target === currentVideoElement) {
  144. isVideoPlaying = false;
  145. currentVideoElement = null;
  146. if (!document.hidden) {
  147. deactivateOverride();
  148. }
  149. console.log(platform + ": Video ended.");
  150. }
  151. });
  152.  
  153. document.addEventListener('visibilitychange', () => {
  154. if (document.hidden && isVideoPlaying) {
  155. activateOverride();
  156. } else if (!document.hidden && isOverrideActive) {
  157. deactivateOverride();
  158. }
  159. });
  160. }
  161.  
  162. const hostname = window.location.hostname;
  163. if (hostname.includes("google.com")) {
  164. googleVideoPlayback();
  165. } else if (hostname.includes("tiktok.com")) {
  166. socialVideoPlayback("TikTok");
  167. } else if (hostname.includes("instagram.com")) {
  168. socialVideoPlayback("IG");
  169. }
  170. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址