Cycle Playback Speed

Cycles through video speed values by pressing 'S' on hovered videos with 4chanX

  1. // ==UserScript==
  2. // @name Cycle Playback Speed
  3. // @version 1.1
  4. // @description Cycles through video speed values by pressing 'S' on hovered videos with 4chanX
  5. // @author kpganon
  6. // @license MIT
  7. // @namespace https://github.com/kpg-anon/scripts
  8. // @include /^https?:\/\/boards\.4chan(nel)?\.org\/.*\/thread\/.*$/
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. let hoveredVideo = null;
  16. const playbackSpeeds = [0.25, 0.4, 0.5, 1.0];
  17.  
  18. const indicator = document.createElement('div');
  19. indicator.style.position = 'fixed';
  20. indicator.style.bottom = '40px';
  21. indicator.style.right = '10px';
  22. indicator.style.zIndex = '10000';
  23. indicator.style.background = 'rgba(0, 0, 0, 0.7)';
  24. indicator.style.color = 'white';
  25. indicator.style.padding = '5px 10px';
  26. indicator.style.borderRadius = '5px';
  27. indicator.style.display = 'none';
  28. document.body.appendChild(indicator);
  29.  
  30. function updateIndicator() {
  31. if (hoveredVideo) {
  32. indicator.textContent = `Playback: ${hoveredVideo.playbackRate}x`;
  33. }
  34. }
  35.  
  36. function setHoveredVideo(videoElement) {
  37. hoveredVideo = videoElement;
  38. indicator.style.display = 'block';
  39. updateIndicator();
  40. }
  41.  
  42. const observer = new MutationObserver(mutations => {
  43. mutations.forEach(mutation => {
  44. mutation.addedNodes.forEach(node => {
  45. if (node.tagName === 'VIDEO') {
  46. setHoveredVideo(node);
  47. }
  48. });
  49. });
  50. });
  51.  
  52. observer.observe(document.body, { childList: true, subtree: true });
  53.  
  54. document.body.addEventListener('keydown', event => {
  55. if (event.key === 's' && hoveredVideo) {
  56. const currentSpeedIndex = playbackSpeeds.indexOf(hoveredVideo.playbackRate);
  57. let newSpeedIndex = currentSpeedIndex + 1;
  58.  
  59. if (newSpeedIndex >= playbackSpeeds.length) {
  60. newSpeedIndex = 0;
  61. }
  62.  
  63. hoveredVideo.playbackRate = playbackSpeeds[newSpeedIndex];
  64. updateIndicator();
  65. }
  66. });
  67.  
  68. document.body.addEventListener('mouseout', event => {
  69. if (hoveredVideo && (event.relatedTarget === null || event.relatedTarget.nodeName !== 'VIDEO')) {
  70. hoveredVideo = null;
  71. indicator.style.display = 'none';
  72. }
  73. });
  74. })();