Prevent off-screen HTML5 autoplay

Disable autoplay for HTML5 media elements displayed outside the visible portion of the page

目前為 2016-10-10 提交的版本,檢視 最新版本

  1. // ==UserScript==//
  2. // @name Prevent off-screen HTML5 autoplay
  3. // @description Disable autoplay for HTML5 media elements displayed outside the visible portion of the page
  4. // @version 1.0
  5. // @author wOxxOm
  6. // @namespace wOxxOm.scripts
  7. // @license MIT License
  8. // @match *://*/*
  9. // @run-at document-start
  10. // @grant GM_info
  11. // ==/UserScript==
  12.  
  13. var checkQueue = [];
  14. var callee;
  15.  
  16. window.addEventListener('message', function(e) {
  17. // some stupid sites choke on object data
  18. if (!/^\{/.test(e.data))
  19. return;
  20. var data = tryParse(e.data);
  21. if (!data || data.name != GM_info.script.name)
  22. return;
  23. switch (data.action) {
  24. case 'querypos':
  25. var iframes = document.getElementsByTagName('iframe');
  26. for (var i = 0, f; (f = iframes[i++]); ) {
  27. if (f.contentWindow == e.source) {
  28. if (window == parent) {
  29. var b = f.getBoundingClientRect();
  30. data.bounds = {l:b.left, t:b.top, r:b.right, b:b.bottom};
  31. data.window = {w:innerWidth, h:innerHeight};
  32. data.action = 'gotpos';
  33. e.source.postMessage(JSON.stringify(data), '*');
  34. } else {
  35. callee = f;
  36. parent.postMessage(e.data, '*');
  37. }
  38. return;
  39. }
  40. }
  41. break;
  42. case 'gotpos':
  43. if (!callee)
  44. return autoplaySentryCheck(data);
  45. if (!callee.parentNode) {
  46. callee = null;
  47. return;
  48. }
  49. var bounds = callee.getBoundingClientRect();
  50. data.bounds.l += bounds.left;
  51. data.bounds.t += bounds.top;
  52. data.bounds.r = Math.min(data.window.w, bounds.left + data.bounds.r);
  53. data.bounds.b = Math.min(data.window.h, bounds.top + data.bounds.b);
  54. callee.contentWindow.postMessage(JSON.stringify(data), '*');
  55. callee = null;
  56. break;
  57. }
  58. });
  59.  
  60. document.addEventListener('play', autoplaySentry, true);
  61.  
  62. function autoplaySentry(e) {
  63. checkQueue.push(e.target);
  64. if (window.parent == window) {
  65. autoplaySentryCheck({
  66. bounds: {l:0, t:0, r:innerWidth, b:innerHeight},
  67. window: {w:innerWidth, h:innerHeight}
  68. });
  69. } else {
  70. parent.postMessage(JSON.stringify({name: GM_info.script.name, action: 'querypos'}), '*');
  71. }
  72. }
  73.  
  74. function autoplaySentryCheck(data) {
  75. while (checkQueue.length) {
  76. var el = checkQueue.pop();
  77. for (var elWithBounds = el, bounds;
  78. elWithBounds &&
  79. (bounds = elWithBounds.getBoundingClientRect()) &&
  80. !bounds.left && !bounds.right && !bounds.top && !bounds.bottom;
  81. elWithBounds = elWithBounds.parentElement) {}
  82. if (bounds.right < data.bounds.l ||
  83. bounds.bottom < data.bounds.t ||
  84. bounds.left > Math.min(data.window.w, data.bounds.r) ||
  85. bounds.top > Math.min(data.window.h, data.bounds.b))
  86. {
  87. console.warn('Preventing off-screen autoplay on %O', el);
  88. el.autoplay = false;
  89. el.pause();
  90. }
  91. }
  92. }
  93.  
  94. function tryParse(str) {
  95. try { return JSON.parse(str); }
  96. catch(e) {}
  97. }

QingJ © 2025

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