Media Speed Changer

Enables you to change the speed of video and audio with hotkeys (even if the media is inside an iframe)

当前为 2022-02-10 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Media Speed Changer
  3. // @description Enables you to change the speed of video and audio with hotkeys (even if the media is inside an iframe)
  4. // @author BLBC (github.com/hjk789, greasyfork.org/users/679182-hjk789)
  5. // @copyright 2020+, BLBC (github.com/hjk789, greasyfork.org/users/679182-hjk789)
  6. // @version 1.2.1
  7. // @homepage https://github.com/hjk789/Userscripts/tree/master/Media-Speed-Changer
  8. // @license https://github.com/hjk789/Userscripts/tree/master/Media-Speed-Changer#license
  9. // @grant none
  10. // @include *
  11. // @namespace https://greasyfork.org/users/679182
  12. // ==/UserScript==
  13.  
  14. document.onkeyup = function(e)
  15. {
  16. if (e.shiftKey && e.key == "Pause") changeSpeed(0.25, "relative")
  17. else if (e.shiftKey && e.key == "PrintScreen") changeSpeed(-0.25,"relative")
  18. else if (e.key == "Pause") changeSpeed(0.5, "relative")
  19. else if (e.key == "PrintScreen") changeSpeed(-0.5, "relative")
  20. else if (e.shiftKey && e.key == "ScrollLock") changeSpeed(1)
  21. else if (e.shiftKey && e.key == "Insert") changeSpeed(3)
  22. else if (e.ctrlKey && (e.key == "Cancel" || e.key == "ScrollLock")) changeSpeed(4) // Ctrl + ScrollLock/Pause = Cancel
  23. else if (e.key == "ScrollLock") changeSpeed(2)
  24. else if (e.ctrlKey && e.key == "Insert") changeSpeed(8)
  25. else if (e.key == "Insert") changeSpeed(16)
  26. }
  27.  
  28. function changeSpeed(value, mode = "absolute")
  29. {
  30. let medias = Array.from(document.querySelectorAll("video, audio"))
  31. try { medias = medias.concat(Array.from(window.top.document.querySelectorAll("video, audio"))) }
  32. catch(e) {}
  33.  
  34. for (let i=0; i < medias.length; i++)
  35. medias[i].playbackRate = (mode == "absolute" ? value : medias[i].playbackRate + value)
  36.  
  37. for (let i=0; i < window.frames.length; i++)
  38. window.frames[i].postMessage("changeSpeed(" + value + ",'" + mode + "')", "*")
  39. }
  40.  
  41. if (window.self == window.top)
  42. {
  43. // Workaround for GreaseMonkey's bug of not running inside IFRAMEs. But there are some embeded medias that still won't have the script running in it,
  44. // like YouTube's embeds. You'll have to use another script-engine, like Tampermonkey or Violentmonkey.
  45.  
  46. if (typeof GM_info != "undefined" && GM_info.scriptHandler == "Greasemonkey")
  47. {
  48. setInterval(function() // For sites that lazy-load the iframes
  49. {
  50. const iframes = document.querySelectorAll("iframe")
  51.  
  52. for (let i=0; i < iframes.length; i++)
  53. {
  54. if (/youtube|player|video|\.mp4|audio/.test(iframes[i].src) && !/comments/.test(iframes[i].src)) // Only frames that are likely for media embedding
  55. {
  56. const frameParent = iframes[i].offsetParent
  57. frameParent.innerHTML = frameParent.innerHTML.replace(/(<iframe .+?) src=/, "$1 data=").replace("<iframe ","<object ") // Change the IFRAME element to an OBJECT element, so that the script can run inside it
  58. }
  59. }
  60.  
  61. }, 2000)
  62. }
  63.  
  64. }
  65. else
  66. {
  67. window.addEventListener("message", function(e){
  68. try { eval(e.data) } // Some frames have CSP protection, which throws an error and breaks the script. This try-catch prevents it from breaking.
  69. catch(e) {}
  70. })
  71. }