YouTube No Cookie Video Player

YouTube で動画を再生する際、埋め込み動画 (No Cookie Video) を表示できます。プライバシー強化モードで視聴したい人に適しています。

  1. // ==UserScript==
  2. // @name YouTube No Cookie Video Player
  3. // @namespace https://kuds.win/
  4. // @version 1.1
  5. // @description YouTube で動画を再生する際、埋め込み動画 (No Cookie Video) を表示できます。プライバシー強化モードで視聴したい人に適しています。
  6. // @author KUDs
  7. // @match https://www.youtube.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  9. // @grant none
  10. // @license GPL-3.0-or-later
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let lastVideoId = '';
  17.  
  18. function attemptUpdateEmbedVideo() {
  19. const videoId = getVideoId();
  20. if (videoId && videoId !== lastVideoId) {
  21. const existingIframeContainer = document.querySelector('.embed-video-container');
  22. if (existingIframeContainer) {
  23. existingIframeContainer.remove();
  24. }
  25. if (!document.getElementById('toggleEmbedVideo')) {
  26. addToggleButton();
  27. }
  28. insertEmbedVideo(videoId);
  29. lastVideoId = videoId;
  30. }
  31. }
  32.  
  33. function getVideoId() {
  34. const urlParams = new URLSearchParams(window.location.search);
  35. return urlParams.get('v');
  36. }
  37.  
  38. function insertEmbedVideo(videoId) {
  39. const iframeContainer = document.createElement('div');
  40. iframeContainer.classList.add('embed-video-container');
  41. const toggleButton = document.getElementById('toggleEmbedVideo');
  42. iframeContainer.style.display = toggleButton && toggleButton.dataset.state === 'visible' ? 'block' : 'none';
  43.  
  44. Object.assign(iframeContainer.style, {
  45. position: 'fixed',
  46. bottom: '20px',
  47. right: '20px',
  48. width: '560px',
  49. height: '315px',
  50. zIndex: '1000',
  51. boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
  52. borderRadius: '10px',
  53. overflow: 'hidden'
  54. });
  55.  
  56. iframeContainer.innerHTML = `
  57. <h1 style="color:red; margin: 0; padding: 10px; background-color: #000;">No Cookie Video</h1>
  58. <iframe id="ytplayer" type="text/html"
  59. src="https://www.youtube-nocookie.com/embed/${videoId}?autoplay=0&fs=1"
  60. frameborder="0" allow="fullscreen; picture-in-picture"
  61. style="width: 100%; height: calc(100% - 40px);"></iframe>`;
  62.  
  63. document.body.appendChild(iframeContainer);
  64. }
  65.  
  66. function addToggleButton() {
  67. const targetElement = document.getElementById('logo');
  68. const toggleButton = document.createElement('button');
  69. toggleButton.id = 'toggleEmbedVideo';
  70. toggleButton.dataset.state = 'visible';
  71. toggleButton.textContent = 'NoCookie';
  72. applyButtonStyles(toggleButton);
  73.  
  74. toggleButton.addEventListener('mouseover', () => {
  75. Object.assign(toggleButton.style, {
  76. filter: 'brightness(1.25)',
  77. transform: 'scale(1.05)',
  78. });
  79. });
  80.  
  81. toggleButton.addEventListener('mouseout', () => {
  82. Object.assign(toggleButton.style, {
  83. filter: 'brightness(1)',
  84. transform: 'scale(1)',
  85. });
  86. });
  87.  
  88. toggleButton.addEventListener('click', function() {
  89. const embedVideoContainer = document.querySelector('.embed-video-container');
  90. if (this.dataset.state === 'hidden') {
  91. this.dataset.state = 'visible';
  92. this.textContent = 'NoCookie';
  93. this.style.backgroundColor = 'red';
  94. if (embedVideoContainer) embedVideoContainer.style.display = 'block';
  95. } else {
  96. this.dataset.state = 'hidden';
  97. this.textContent = 'Normal';
  98. this.style.backgroundColor = 'gray';
  99. if (embedVideoContainer) embedVideoContainer.style.display = 'none';
  100. }
  101. });
  102.  
  103. targetElement.insertAdjacentElement('afterend', toggleButton);
  104. }
  105.  
  106. function applyButtonStyles(button) {
  107. Object.assign(button.style, {
  108. backgroundColor: 'red',
  109. color: 'white',
  110. border: 'none',
  111. borderRadius: '10px',
  112. padding: '10px 20px',
  113. fontSize: '16px',
  114. cursor: 'pointer',
  115. transition: 'filter 0.3s, transform 0.3s',
  116. marginLeft: '20px',
  117. });
  118. }
  119.  
  120. const pushState = history.pushState;
  121. history.pushState = function() {
  122. pushState.apply(history, arguments);
  123. attemptUpdateEmbedVideo();
  124. };
  125. window.addEventListener('popstate', attemptUpdateEmbedVideo);
  126. new MutationObserver(attemptUpdateEmbedVideo).observe(document.body, {childList: true, subtree: true});
  127.  
  128. attemptUpdateEmbedVideo();
  129. })();