Zoom Cloud Playback keyboard shortcut control

player keyboard control

  1. // ==UserScript==
  2. // @name Zoom Cloud Playback keyboard shortcut control
  3. // @namespace http://tampermonkey.net/
  4. // @include *.zoom.us/*
  5. // @version 1.2
  6. // @description player keyboard control
  7. // @author VinC
  8. // @grant none
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. // User input.
  13. window.addEventListener("keydown", keydown);
  14.  
  15. // User determined events.
  16. function keydown (event) {
  17. // Spacebar: Play/Pause
  18. if (event.keyCode == 32) {
  19. document.getElementsByClassName('vjs-play-control')[0].click();
  20. }
  21. // k key: Play/Pause
  22. if (event.keyCode == 75) {
  23. document.getElementsByClassName('vjs-play-control')[0].click();
  24. }
  25. // c key: captions
  26. if (event.keyCode == 67) {
  27. document.getElementsByClassName('vjs-captions-control-button')[0].click();
  28. }
  29. // f key: full scree
  30. if (event.keyCode == 70) {
  31. document.getElementsByClassName('vjs-fullscreen-toggle-control-button')[0].click();
  32. }
  33. }
  34.  
  35.  
  36. /*
  37. Notes:
  38.  
  39. - This script is designed for US keyboards. Some shortcuts won't work on non US keyboard. Non US keyboard users will need to edit keys in the script.
  40.  
  41. - In YouTube, if the video speed is below 0.25x or above 2x, the YouTube setting display will be capped to 0.1x or 2x.
  42. - Web browser video speeds: Firefox = 0.25 to 5.0; Chrome = 0.1 to 16.0.
  43.  
  44.  
  45. Keyboard Shortcuts:
  46.  
  47. j = Rewind media by 5 seconds
  48. k = Fast forward media by 5 seconds
  49. LEFT = Rewind media by 5 seconds
  50. RIGHT = Fast forward media by 5 seconds
  51. SHIFT+LEFT = Rewind media by 30 seconds
  52. SHIFT+RIGHT = Fast forward media by 30 seconds
  53. SHIFT+LEFT = Rewind media by 30 seconds
  54. SHIFT+j = Fast forward media by 30 seconds
  55. CTRL+l = Rewind media by 1 minute
  56. CTRL+RIGHT = Fast forward media by 1 minute
  57. CTRL+SHIFT+LEFT = Rewind media by 5 minutes
  58. CTRL+SHIFT+RIGHT = Fast forward media by 5 minutes
  59. CTRL+/ = Fast forward media by 1.5 minutes
  60. 0 to 9 = Seek media to 0%, 10%, 20%,...90%
  61. SHIFT+0 to SHIFT+9 = Seek media to 5%, 15%, 25%,...95%
  62. CTRL+1 to CTRL+5 = Change audio volume to 20%, 40%, 60$, 80%, 100%
  63. vinc:SHIFT+< = Decrease media speed by 0.2x (by default)
  64. vinc:z = Decrease media speed by 0.2x (by default)
  65. vinc:SHIFT+ = Increase media speed by 0.2x (by default)
  66. vinc:x = Increase media speed by 0.2x (by default)
  67. CTRL+; = Reset media speed
  68. CTRL+' = Change custom media speed
  69. CTRL+\ = Change unit of media speed increment/decrement
  70.  
  71. For Widescreen Video Viewport:
  72. CTRL+6 = Zoom ultra widescreen content to remove top+bottom borders, but also remove left+right content a bit.
  73. CTRL+7 = Change video aspect ratio for letterbox content. Fix 4:3 letterbox content stretched to widescreen format.
  74. CTRL+8 = Change video aspect ratio for TV content. Fix 4:3 TV content stretched to widescreen format.
  75.  
  76. For 4:3 TV Video Viewport:
  77. CTRL+SHIFT+6 = Change video aspect ratio for ultra widescreen content. Fix ultra widescreen content compressed into 4:3 TV format.
  78. CTRL+SHIFT+7 = Zoom 4:3 letterbox content to remove half of top+bottom borders, but also remove left+right content a little.
  79. This can also be used to half-zoom ultra widescreen content on widescreen viewport. i.e. half-zoom of CTRL+6.
  80. CTRL+SHIFT+8 = Change video aspect ratio for widescreen content. Fix widescreen content compressed into 4:3 TV format.
  81.  
  82. For Any Video Viewport:
  83. CTRL+9 = Reset video aspect ratio
  84. */
  85.  
  86. ((eleOSD, osdTimer) => {
  87.  
  88. //=== CONFIGURATION BEGIN ===
  89.  
  90. //Video speed increment/decrement unit.
  91. var incrementUnit = 0.2;
  92.  
  93. //Duration (in milliseconds) to display On Screen Display (OSD) when changing playback rate. Set to zero or less to disable.
  94. var osdTimeout = 3000;
  95.  
  96. //Keyboard shortcuts.
  97. //key = Key name. String type if single shortcut, or array of string if multiple shortcut (for single function multiple shortcuts).
  98. // Each key name can either be the character which is produced by the key (e.g. `a`, `4`, `*`, etc.),
  99. // or the code name for the key (e.g. `Digit2`, `BracketLeft`, etc.). Both types are case sensitive.
  100. // When SHIFT modifier is used with keys which produces a character, key code name should be used.
  101. // A list of key code names can be found here: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
  102. //modifiers = Any combinations of "C", "S", and "A", for Ctrl, Shift, and Alt keys.
  103. var keys = [
  104. { //ctrl+space: seek media to next frame (only when paused. firefox only)
  105. key: " ", modifiers: "C",
  106. func: (key, ele) => ele.seekToNextFrame && ele.seekToNextFrame()
  107. },
  108. { //0 to 9: seek media to 0%,10%,20%,...90%
  109. key: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], modifiers: "",
  110. func: (ele, key, keyIndex) => ele.currentTime = keyIndex / 10 * ele.duration
  111. },
  112. { //shift+0 to shift+9: seek media to 5%,15%,25%,...95%
  113. key: [")", "!", "@", "#", "$", "%", "^", "&", "*", "("], modifiers: "S",
  114. func: (ele, key, keyIndex) => ele.currentTime = (keyIndex + 0.5) / 10 * ele.duration
  115. },
  116. { //ctrl+1 to ctrl+5: set audio volume to 20%,40%,60%,80%,100%
  117. key: ["1", "2", "3", "4", "5"], modifiers: "C",
  118. func: (ele, key, keyIndex) => updAudioVolume(ele, (parseInt(key) * 2) / 10)
  119. },
  120. { //vinc:j: rewind media by 5 seconds
  121. key: "j", modifiers: "",
  122. func: (ele, key) => ele.currentTime -= 5
  123. },
  124. { //vinc:left: rewind media by 5 seconds
  125. key: "ArrowLeft", modifiers: "",
  126. func: (ele, key) => ele.currentTime -= 5
  127. },
  128. { //shift+left: rewind media by 30 seconds
  129. key: "ArrowLeft", modifiers: "S",
  130. func: (ele, key) => ele.currentTime -= 30
  131. },
  132. { //shift+left: rewind media by 30 seconds
  133. key: "j", modifiers: "S",
  134. func: (ele, key) => ele.currentTime -= 30
  135. },
  136. { //ctrl+left: rewind media by 1 minute
  137. key: "ArrowLeft", modifiers: "C",
  138. func: (ele, key) => ele.currentTime -= 60
  139. },
  140. { //ctrl+shift+left: rewind media by 5 minutes
  141. key: "ArrowLeft", modifiers: "CS",
  142. func: (ele, key) => ele.currentTime -= 300
  143. },
  144. { //vinc:k: fast forward media by 5 seconds
  145. key: "l", modifiers: "",
  146. func: (ele, key) => ele.currentTime += 5
  147. },
  148. { //vinc:right: fast forward media by 5 seconds
  149. key: "ArrowRight", modifiers: "",
  150. func: (ele, key) => ele.currentTime += 5
  151. },
  152. { //shift+right: fast forward media by 30 seconds
  153. key: "ArrowRight", modifiers: "S",
  154. func: (ele, key) => ele.currentTime += 30
  155. },
  156. { //shift+right: fast forward media by 30 seconds
  157. key: "k", modifiers: "S",
  158. func: (ele, key) => ele.currentTime += 30
  159. },
  160. { //ctrl+right: fast forward media by 1 minute
  161. key: "ArrowRight", modifiers: "C",
  162. func: (ele, key) => ele.currentTime += 60
  163. },
  164. { //ctrl+shift+right: fast forward media by 5 minutes
  165. key: "ArrowRight", modifiers: "CS",
  166. func: (ele, key) => ele.currentTime += 300
  167. },
  168. { //ctrl+/: fast forward media by 1.5 minutes
  169. key: "/", modifiers: "CS",
  170. func: (ele, key) => ele.currentTime += 90
  171. },
  172. { //vinc:shift+<: decrease media speed by 0.2
  173. key: "<", modifiers: "S",
  174. func: (ele, key) => {
  175. key = ele.playbackRate - incrementUnit;
  176. if (key < 0.1) {
  177. key = 0.1;
  178. } else if ((key < 1) && (ele.playbackRate > 1)) key = 1;
  179. updVideoSpeed(ele, key);
  180. }
  181. },
  182. { //vinc:z: decrease media speed by 0.2
  183. key: "z", modifiers: "",
  184. func: (ele, key) => {
  185. key = ele.playbackRate - incrementUnit;
  186. if (key < 0.1) {
  187. key = 0.1;
  188. } else if ((key < 1) && (ele.playbackRate > 1)) key = 1;
  189. updVideoSpeed(ele, key);
  190. }
  191. },
  192. { //vinc:shift+> increase media speed by 0.2
  193. key: ">", modifiers: "S",
  194. func: (ele, key) => {
  195. key = ele.playbackRate + incrementUnit;
  196. if (key > 16) {
  197. key = 16;
  198. } else if ((key > 1) && (ele.playbackRate < 1)) key = 1;
  199. updVideoSpeed(ele, key);
  200. }
  201. },
  202. { //vinc:x increase media speed by 0.2
  203. key: "x", modifiers: "",
  204. func: (ele, key) => {
  205. key = ele.playbackRate + incrementUnit;
  206. if (key > 16) {
  207. key = 16;
  208. } else if ((key > 1) && (ele.playbackRate < 1)) key = 1;
  209. updVideoSpeed(ele, key);
  210. }
  211. },
  212. { //ctrl+;: reset media speed to 1x
  213. key: ";", modifiers: "C",
  214. func: (ele, key) => updVideoSpeed(ele, 1)
  215. },
  216. { //ctrl+': use custom media speed
  217. key: "'", modifiers: "C",
  218. func: (ele, key) => {
  219. if ((key = prompt("Enter media speed from 0.1 to 16 (inclusive).\ne.g.: 1 = Normal, 0.5 = Half, 2 = Double, 3 = Triple, etc.", ele.playbackRate)) === null) return;
  220. if (isNaN(key = parseFloat(key.trim()))) {
  221. alert("Input must be a number.");
  222. return;
  223. }
  224. updVideoSpeed(ele, (key = parseFloat(key.toFixed(1))) < 0.1 ? 0.1 : (key > 16 ? 16 : key));
  225. }
  226. },
  227. { //ctrl+\: change unit of media speed increment/decrement
  228. key: "\\", modifiers: "C",
  229. func: (ele, key) => {
  230. if ((key = prompt("Enter unit of media speed increment/decrement from 0.1 to 4 (inclusive).", incrementUnit)) === null) return;
  231. if (!isNaN(key = parseFloat(key.trim()))) {
  232. incrementUnit = (key = parseFloat(key.toFixed(1))) < 0.1 ? 0.1 : (key > 4 ? 4 : key);
  233. } else alert("Input must be a number.");
  234. }
  235. },
  236. { //ctrl+6: Zoom ultra widescreen
  237. key: "6", modifiers: "C", videoOnly: true,
  238. func: (ele, key) => updVideoAspect("scale(1.3333)", "Ultra Widescreen Zoom")
  239. },
  240. { //ctrl+7: Letterbox aspect ratio
  241. key: "7", modifiers: "C", videoOnly: true,
  242. func: (ele, key) => updVideoAspect("scaleY(1.3333)", "Letterbox")
  243. },
  244. { //ctrl+8: TV aspect ratio
  245. key: "8", modifiers: "C", videoOnly: true,
  246. func: (ele, key) => updVideoAspect("scaleX(0.75)", "TV")
  247. },
  248. { //ctrl+shift+6: Ultra widescreen aspect ratio
  249. key: "Digit6", modifiers: "CS", videoOnly: true,
  250. func: (ele, key) => updVideoAspect("scaleY(0.7168)", "Ultra Widescreen")
  251. },
  252. { //ctrl+shift+7: Half-zoom letterbox
  253. key: "Digit7", modifiers: "CS", videoOnly: true,
  254. func: (ele, key) => updVideoAspect("scale(1.1666)", "Letterbox Half-Zoom")
  255. },
  256. { //ctrl+shift+8: Widescreen aspect ratio
  257. key: "Digit8", modifiers: "CS", videoOnly: true,
  258. func: (ele, key) => updVideoAspect("scaleY(0.5625)", "Widescreen")
  259. },
  260. { //ctrl+9: reset video aspect ratio
  261. key: "9", modifiers: "C", videoOnly: true,
  262. func: (ele, key) => updVideoAspect("", "Reset")
  263. }
  264. ];
  265. keys.forEach((k, s, m) => {
  266. s = k.modifiers.toUpperCase();
  267. k.modifiers = {ctrl: s.includes("C"), shift: s.includes("S"), alt: s.includes("A")};
  268. });
  269.  
  270. //=== CONFIGURATION END ===
  271.  
  272. function showOSD(s) {
  273. if (osdTimeout < 0) return;
  274. if (eleOSD) {
  275. eleOSD.textContent = s;
  276. } else {
  277. eleOSD = document.createElement("DIV");
  278. eleOSD.style.cssText = "position:fixed;z-index:999999999;right:.5rem;bottom:.5rem;margin:0;padding:.2rem .5rem .1rem .5rem;width:auto;height:auto;font:normal 16pt/normal sans-serif;background:#444;color:#fff";
  279. eleOSD.textContent = s;
  280. document.body.appendChild(eleOSD);
  281. }
  282. clearTimeout(osdTimer);
  283. osdTimer = setTimeout(() => {
  284. eleOSD.remove();
  285. eleOSD = null;
  286. }, osdTimeout);
  287. }
  288.  
  289. function stopEvent(ev) {
  290. ev.preventDefault();
  291. ev.stopPropagation();
  292. ev.stopImmediatePropagation();
  293. }
  294.  
  295. function updVideoSpeed(ele, spd, e) {
  296. if ((location.hostname === "www.youtube.com") && (e = ele.parentNode.parentNode).setPlaybackRate && (spd >= 0.25) && (spd <= 2)) {
  297. e.setPlaybackRate(spd = parseFloat(spd.toFixed(1)));
  298. } else ele.playbackRate = spd = parseFloat(spd.toFixed(1));
  299. showOSD("Speed " + spd + "x");
  300. }
  301.  
  302. function updVideoAspect(asp, label, s) {
  303. if (!(s = document.getElementById("vidAspOvr"))) document.body.appendChild(s = document.createElement("STYLE")).id = "vidAspOvr";
  304. s.innerHTML = asp ? `video{transform:${asp}!important}` : "";
  305. showOSD("Ratio: " + label);
  306. }
  307.  
  308. function updAudioVolume(ele, vol) {
  309. if ((location.hostname === "www.youtube.com") && (e = ele.parentNode.parentNode).setVolume) {
  310. e.setVolume(vol * 100);
  311. } else ele.volume = vol;
  312. showOSD("Audio " + (vol * 100) + "%");
  313. }
  314.  
  315. incrementUnit = parseFloat((incrementUnit < 0.1 ? 0.1 : (incrementUnit > 1 ? 1 : incrementUnit)).toFixed(1));
  316. addEventListener("keydown", function(ev, ele) {
  317. if ((!(ele = document.activeElement) || !((ele.contentEditable === "true") || ["BUTTON", "INPUT", "SELECT", "TEXTAREA"].includes(ele.tagName))) && (ele = document.querySelector("video,audio"))) {
  318. keys.some((k, a, i) => {
  319. a = Array.isArray(k.key);
  320. if (
  321. ((!a && ((k.key === ev.key) || (k.key === ev.code))) || (a && (((i = k.key.indexOf(ev.key)) >= 0) || ((i = k.key.indexOf(ev.code)) >= 0)))) &&
  322. (k.modifiers.ctrl === ev.ctrlKey) && (k.modifiers.shift === ev.shiftKey) && (k.modifiers.alt === ev.altKey) &&
  323. (!k.videoOnly || (ele.tagName === "VIDEO"))
  324. ) {
  325. stopEvent(ev);
  326. k.func(ele, ev.key, a ? i : null);
  327. return true;
  328. }
  329. });
  330. }
  331. }, true);
  332.  
  333. })();