Loop exercise videos

Exercise videos will loop, press space to start playing, press F for full screen.

  1. // ==UserScript==
  2. // @name Loop exercise videos
  3. // @namespace Itsnotlupus Industries
  4. // @version 1.0
  5. // @description Exercise videos will loop, press space to start playing, press F for full screen.
  6. // @author itsnotlupus
  7. // @license MIT
  8. // @match https://www.muscleandstrength.com/exercises/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=muscleandstrength.com
  10. // @grant none
  11. // ==/UserScript==
  12. /* global Vimeo, YT */
  13. /* jshint esversion: 11 */
  14.  
  15. // Videos seen so far are one of
  16. // 1. adhoc flowplayer with <video> tags
  17. // 2. embedded Vimeo players
  18. // 3. embedded Youtube players
  19. // Each type needs its own handling to loop and control playback.
  20.  
  21. document.head.append(Object.assign(document.createElement('script'), { src: "https://www.youtube.com/iframe_api" }));
  22. document.head.append(Object.assign(document.createElement('script'), { src: "https://player.vimeo.com/api/player.js" }));
  23.  
  24. function onYouTubeIframeAPIReady() {
  25. console.log("YOUTUBE IFRAME API READY!");
  26. }
  27.  
  28. function init() {
  29. const video = document.querySelector('video');
  30. const iframe = document.querySelector('iframe');
  31. if (!video && !iframe) return setTimeout(init, 1000);
  32. if (!window.YT) return setTimeout(init, 1000);
  33. if (!window.Vimeo) return setTimeout(init, 1000);
  34. let player; // youtube or vimeo player API.
  35. if (video) {
  36. console.log('found old video, adding loop attribute');
  37. video.loop = true;
  38. } else if (iframe) {
  39. const url = new URL(iframe.src);
  40. if (url.host.includes('youtube')) {
  41. console.log('found youtube video, adding loop and loading player object');
  42. const id = url.pathname.split('/').at(-1);
  43. iframe.src += '&enablejsapi=1&mute=1&loop=1&playlist=' + id;
  44. iframe.id = iframe.id || 'YoutubeVideoWidget';
  45. player = new YT.Player(iframe.id);
  46. } else if (url.host.includes('vimeo')) {
  47. console.log('found vimeo video, adding loop and loading player object');
  48. iframe.src += '&loop=1';
  49. player = new Vimeo.Player(iframe);
  50. } else {
  51. return setTimeout(init, 1000);
  52. }
  53. }
  54. // full screen toggling by pressing "F"
  55. const fullscreen = (e=document.documentElement, d=e.ownerDocument) => d.fullscreenElement ? d.exitFullscreen() : e.requestFullscreen();
  56. addEventListener('keypress', async e=> {
  57. if (document.activeElement != document.body) return; // don't mess with text fields.
  58. if (e.key == 'f') {
  59. e.preventDefault();
  60. fullscreen(video?.parentElement?.parentElement ?? iframe);
  61. }
  62. if (e.key == ' ') {
  63. e.preventDefault();
  64. if (video) document.querySelector('.fp-ui').click();
  65. if (iframe) {
  66. const url = new URL(iframe.src);
  67. if (url.host.includes('youtube')) {
  68. if (player.getPlayerState() == 1) {
  69. player.pauseVideo();
  70. } else {
  71. player.playVideo();
  72. }
  73. } else {
  74. // vimeo, probably
  75. const paused = await player.getPaused();
  76. if (paused) {
  77. player.play();
  78. } else {
  79. player.pause();
  80. }
  81. }
  82. }
  83. }
  84. });
  85. }
  86.  
  87. init();

QingJ © 2025

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