YouTube Exit Fullscreen on Video End (Modified)

Exit YouTube fullscreen when a video finishes playing (disabled for playlists)

目前为 2023-06-29 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Exit Fullscreen on Video End (Modified)
  3. // @namespace https://www.youtube.com/
  4. // @version 1.2.1
  5. // @description Exit YouTube fullscreen when a video finishes playing (disabled for playlists)
  6. // @author CY Fung
  7. // @match *://www.youtube.com/*
  8. // @license MIT
  9. // @icon https://www.google.com/s2/favicons?domain=youtube.com
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. let lastPause = 0;
  16. let lastFullscreenEnded = 0;
  17. let observer = null;
  18.  
  19. const check = () => Math.abs(lastFullscreenEnded - lastPause) < 400 && Date.now() - lastPause < 800;
  20.  
  21. const mCallback = (mutations) => {
  22. if (!document.fullscreenElement) return;
  23. let detected = false;
  24. let video = null;
  25. for (const mutation of mutations) {
  26. video = (mutation || 0).target;
  27. if (!video) continue;
  28. const newValue = video.className;
  29. const oldValue = mutation.oldValue;
  30. if (newValue.indexOf("ended-mode") >= 0 && oldValue.indexOf("ended-mode") < 0) {
  31. detected = true;
  32. break;
  33. }
  34. }
  35. if (detected) {
  36. if (video && video.classList.contains("ended-mode")) {
  37. lastFullscreenEnded = Date.now();
  38. check() && endFullscreen(video);
  39. }
  40. }
  41. }
  42.  
  43. const endFullscreen = (elm) => {
  44. lastPause = 0;
  45. lastFullscreenEnded = 0;
  46. const movie_player = HTMLElement.prototype.closest.call(elm, '#movie_player');
  47. const btn = movie_player ? HTMLElement.prototype.querySelector.call(movie_player, '.ytp-fullscreen-button') : null;
  48. if (btn) {
  49. btn.click();
  50. } else {
  51. document.exitFullscreen();
  52. }
  53. }
  54.  
  55. const setup = async () => {
  56. if (location.href.includes("/watch") && !location.href.includes("list=")) {
  57. let videoPlayer = document.getElementById('movie_player');
  58. if (videoPlayer) {
  59. if (!observer) observer = new MutationObserver(mCallback); else {
  60. observer.disconnect();
  61. observer.takeRecords();
  62. }
  63. observer.observe(videoPlayer, {
  64. attributes: true,
  65. attributeFilter: ['class'],
  66. attributeOldValue: true
  67. });
  68. } else if (observer) {
  69. observer.disconnect();
  70. observer.takeRecords();
  71. observer = null;
  72. }
  73. }
  74. }
  75.  
  76. const onPause = (evt) => {
  77. const target = ((evt || 0).target || 0);
  78. if (!(target instanceof HTMLVideoElement)) return;
  79. if (observer === null) return;
  80. lastPause = Date.now();
  81. check() && endFullscreen(target);
  82. }
  83.  
  84. document.addEventListener('yt-navigate-finish', setup, false);
  85. document.addEventListener('spfdone', setup, true);
  86. document.addEventListener("pause", onPause, true);
  87. setup();
  88. })();

QingJ © 2025

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