youtube HTML5 Auto Loop

youtube再生時に自動ループする

Verze ze dne 12. 12. 2022. Zobrazit nejnovější verzi.

  1. // ==UserScript==
  2. // @name youtube HTML5 Auto Loop
  3. // @namespace youtube HTML5 Auto Loop
  4. // @grant none
  5. // @description youtube再生時に自動ループする
  6. // @author TNB
  7. // @match https://www.youtube.com/*
  8. // @version 1.5
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. 'use strict';
  13.  
  14. const loop_off = {
  15. when_enable_next_video_autoplay: false,
  16. when_playlist: false,
  17. with_embedded_video: false
  18. };
  19.  
  20. const YoutubeHTML5AutoLoop = {
  21. loop: true,
  22. video: null,
  23. prevSrc: null,
  24. button: null,
  25. eventcache: false,
  26. cancelInit: false,
  27. ele: {
  28. when_enable_next_video_autoplay: '.ytp-button:not([style*="display"]) .ytp-autonav-toggle-button[aria-checked="true"]',
  29. when_playlist: '#secondary-inner > #playlist:not([hidden])',
  30. with_embedded_video: 'html[data-cast-api-enabled="true"]'
  31. },
  32. init: function() {
  33. this.addListener();
  34. },
  35. isLoop: function() {
  36. return !Object.keys(loop_off).some(a => loop_off[a] && document.querySelector(this.ele[a]));
  37. },
  38. goLoop: function() {
  39. this.video.currentTime = 0;
  40. this.video.play;
  41. },
  42. loopOn: function() {
  43. if (this.loop) this.video.setAttribute('loop', this.loop);
  44. else this.video.removeAttribute('loop');
  45. },
  46. initLoop: function() {
  47. this.loop = this.isLoop();
  48. this.loopOn();
  49. },
  50. loopToggle: function() {
  51. this.loop = !this.loop;
  52. this.loopOn();
  53. },
  54. loopDisplay: function() {
  55. const video = document.querySelector('video:hover');
  56. if (!video) return;
  57. const checkBox = document.querySelector('.ytp-contextmenu [aria-checked]');
  58. checkBox.setAttribute('aria-checked', this.loop);
  59. if (!this.eventcache) {
  60. checkBox.addEventListener('click', this, true);
  61. this.eventcache = true;
  62. }
  63. },
  64. watchAjax: function() {
  65. if (window != window.parent && document.getElementById('chat')) return;
  66. const mm = new MutationObserver(() => {
  67. const player = document.getElementById('movie_player');
  68. if (!player) return;
  69. this.video = player.querySelector('video');
  70. const mo = new MutationObserver(() => {
  71. if (this.video.src != this.prevSrc) this.cancelInit = false;
  72. if (!this.cancelInit) this.initLoop();
  73. if (this.loop && player.classList.contains('ended-mode')) this.goLoop();
  74. this.prevSrc = this.video.src;
  75. });
  76. mo.observe(player, {attributes: true, attributeFilter: ['class']});
  77.  
  78. const list = document.querySelector('#secondary-inner > #playlist');
  79. const ss = new MutationObserver(() => {
  80. this.initLoop();
  81. });
  82.  
  83. if (list) {
  84. mm.disconnect();
  85. this.initLoop();
  86. if (loop_off.when_playlist) ss.observe(list, {attributes: true, attributeFilter: ['hidden']});
  87. if (loop_off.when_enable_next_video_autoplay) this.addToggleEvent();
  88. }
  89. });
  90. mm.observe(document.body, {childList: true, subtree: true});
  91. },
  92. addToggleEvent: function() {
  93. this.button = document.querySelector('.ytp-autonav-toggle-button');
  94. if (!this.button) return;
  95. this.button.addEventListener('click', () => {
  96. this.loop = JSON.parse(this.button.getAttribute('aria-checked'));
  97. this.cancelInit = true
  98. });
  99. },
  100. addListener: function() {
  101. window.addEventListener('DOMContentLoaded', this);
  102. window.addEventListener('contextmenu', this);
  103. },
  104. handleEvent: function(e) {
  105. switch (e.type) {
  106. case 'DOMContentLoaded':
  107. this.watchAjax();
  108. break;
  109. case 'contextmenu':
  110. this.loopDisplay();
  111. break;
  112. case 'click':
  113. this.loopToggle();
  114. document.body.click();
  115. if (this.button && !document.querySelector('#secondary-inner > #playlist:not([hidden])')) this.button.click();
  116. this.cancelInit = true
  117. e.stopPropagation();
  118. break;
  119. }
  120. }
  121. };
  122.  
  123. YoutubeHTML5AutoLoop.init();