您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
youtube再生時に自動ループする
// ==UserScript== // @name youtube HTML5 Auto Loop // @namespace youtube HTML5 Auto Loop // @grant none // @description youtube再生時に自動ループする // @author TNB // @match https://www.youtube.com/* // @version 1.5.5 // @run-at document-start // ==/UserScript== /******************** SETTING **************************/ const loop_off = { when_enable_next_video_autoplay: false, when_playlist: false, with_embedded_video: false }; /********************************************************/ 'use strict'; const YoutubeHTML5AutoLoop = { loop: true, readyToReload: false, playercontainer: null, video: null, prevSrc: null, button: null, eventcache: {}, cancelInit: false, ele: { when_enable_next_video_autoplay: '.ytp-right-controls > button[style]:not([style *= "display: none"]) .ytp-autonav-toggle-button[aria-checked="true"]', when_playlist: '#secondary-inner #playlist:not([hidden])', with_embedded_video: 'html[data-cast-api-enabled="true"]' }, init: function() { this.addListener(); }, isLoop: function() { return !Object.keys(loop_off).some(a => loop_off[a] && document.querySelector(this.ele[a])); }, goLoop: function() { this.video.currentTime = 0; this.video.play; }, enableLoop: function() { if (this.loop) this.video.setAttribute('loop', ''); else this.video.removeAttribute('loop'); }, initLoop: function() { this.loop = this.isLoop(); this.enableLoop(); }, loopToggle: function() { this.loop = !this.loop; this.enableLoop(); }, displayLoopStatus: function() { const video = document.querySelector('video:hover'); if (!video) return; const checkBox = document.querySelector('.ytp-contextmenu [aria-checked]'); checkBox.setAttribute('aria-checked', this.loop); if (!this.eventcache.checkBox) { checkBox.addEventListener('click', this, true); this.eventcache.checkBox = true; } }, isEnded: function(m) { return m.classList.contains('ended-mode') || m.querySelector('.ytp-autonav-endscreen-button-container:not([style*="display"]),.html5-endscreen:not([style*="display"])'); }, toggleNextVideoAutoplay: function() { if ((!loop_off.when_enable_next_video_autoplay && this.loop) || loop_off.when_enable_next_video_autoplay) { setTimeout(() => { if (document.querySelector(`.ytp-right-controls > button[style]:not([style *= "display: none"]) .ytp-autonav-toggle-button[aria-checked="${this.loop}"]`)) this.button.click(); }, 1000); } }, observeVideo: function() { new MutationObserver(() => { if (this.video.src != this.prevSrc) this.cancelInit = false; if (!this.cancelInit) this.initLoop(); // if (this.loop && this.isEnded(this.playercontainer)) this.goLoop(); if (!this.eventcache.toggleAutoPlay) this.addToggleEvent(); this.toggleNextVideoAutoplay(); this.prevSrc = this.video.src; this.video = this.playercontainer.querySelector('video'); this.video.addEventListener('timeupdate', ()=> { if (this.video.duration - this.video.currentTime < 1 && !this.readyToReload) { this.readyToReload = true; setTimeout(() => {if (this.loop && document.querySelector('.ytp-spinner[style=""]')) location.reload()}, 2000); } }); }).observe(this.playercontainer, {childList: true, subtree: true, attributes: true, attributeFilter: ['class']}); }, findPlayercontainer: function() { if (window != window.parent && document.getElementById('chat')) return; const mo = new MutationObserver(() => { this.playercontainer = document.getElementById('movie_player'); if (!this.playercontainer) return; this.video = this.playercontainer.querySelector('video'); this.observeVideo(); this.initLoop(); this.addToggleEvent(); this.toggleNextVideoAutoplay(); mo.disconnect(); }); mo.observe(document.body, {childList: true, subtree: true}); }, addToggleEvent: function() { this.button = document.querySelector('.ytp-right-controls > button[style]:not([style *= "display: none"]) .ytp-autonav-toggle-button'); if (!loop_off.when_enable_next_video_autoplay || !this.button) return; this.button.addEventListener('click', () => { this.loop = JSON.parse(this.button.getAttribute('aria-checked')); this.enableLoop(); this.cancelInit = true; this.eventcache.toggleAutoPlay = true; }); }, addListener: function() { window.addEventListener('DOMContentLoaded', this); window.addEventListener('contextmenu', this); }, handleEvent: function(e) { switch (e.type) { case 'DOMContentLoaded': this.findPlayercontainer(); break; case 'contextmenu': this.displayLoopStatus(); break; case 'click': this.loopToggle(); document.body.click(); this.toggleNextVideoAutoplay(); this.cancelInit = true; e.stopPropagation(); break; } } }; YoutubeHTML5AutoLoop.init();