Youtubeをプレビュー再生
// ==UserScript== // @name youtubeプレビュー再生機能追加 // @name:en Added youtube preview playback function // @license AMA // @namespace http://tampermonkey.net/ // @version 2.9 // @description Youtubeをプレビュー再生 // @description:en Preview playback of Youtube // @author Your Name // @match https://www.youtube.com/* // @grant none // ==/UserScript== (function() { 'use strict'; let previewVideo = null; let currentVideoId = null; let player; const sizes = [ { width: '320px', height: '180px' }, { width: '640px', height: '360px' }, { width: '1280px', height: '720px' } ]; let currentSizeIndex = 1; document.addEventListener('mouseover', function(e) { let thumbnail = e.target.closest('a#thumbnail'); if (thumbnail) { let url = new URL(thumbnail.href); if (url.pathname.startsWith('/shorts/')) { currentVideoId = url.pathname.split('/shorts/')[1]; } else { currentVideoId = url.searchParams.get('v'); } // 左上にプレビュー再生ボタンを追加 addPreviewButton(thumbnail); } }); function addPreviewButton(thumbnail) { let previewButton = thumbnail.querySelector('.preview-button'); if (!previewButton) { previewButton = document.createElement('button'); previewButton.textContent = 'prev'; previewButton.className = 'preview-button'; previewButton.style.position = 'absolute'; previewButton.style.top = '5px'; previewButton.style.left = '5px'; previewButton.style.zIndex = '1001'; previewButton.style.backgroundColor = 'rgba(255, 255, 255, 0.5)'; // 透明度50% previewButton.style.border = '1px solid #ccc'; previewButton.style.padding = '5px'; previewButton.style.cursor = 'pointer'; previewButton.style.width = thumbnail.offsetWidth + 'px'; // サムネイルと同じ幅 previewButton.style.height = '50px'; // 高さを50pxに設定 previewButton.addEventListener('click', function(event) { event.stopPropagation(); // クリックイベントの伝播を止める event.preventDefault(); // デフォルトの動作を防ぐ if (previewVideo) { stopPreview(); } startPreview(currentVideoId); }); thumbnail.appendChild(previewButton); thumbnail.addEventListener('mouseleave', function() { previewButton.style.display = 'none'; }); thumbnail.addEventListener('mouseenter', function() { previewButton.style.display = 'block'; }); } } document.addEventListener('keydown', function(event) { if (event.key === 'V' && event.shiftKey && currentVideoId) { if (previewVideo) { stopPreview(); } startPreview(currentVideoId); } if (event.key === 'Escape' && previewVideo) { stopPreview(); } }); function startPreview(videoId) { let previewUrl = videoId.includes('shorts') ? `https://www.youtube.com/embed/${videoId}` : `https://www.youtube.com/embed/${videoId}?autoplay=1&enablejsapi=1`; previewVideo = document.createElement('div'); previewVideo.style.position = 'fixed'; previewVideo.style.bottom = '10px'; previewVideo.style.right = '10px'; previewVideo.style.zIndex = '1000'; previewVideo.style.backgroundColor = 'black'; previewVideo.style.width = sizes[currentSizeIndex].width; previewVideo.style.height = sizes[currentSizeIndex].height; let iframe = document.createElement('iframe'); iframe.src = previewUrl; iframe.style.width = '100%'; iframe.style.height = '100%'; iframe.style.border = 'none'; previewVideo.appendChild(iframe); let resizeButton = document.createElement('button'); resizeButton.textContent = '⬜'; resizeButton.style.position = 'absolute'; resizeButton.style.top = '10px'; resizeButton.style.right = '10px'; resizeButton.style.zIndex = '1001'; resizeButton.style.backgroundColor = 'rgba(255, 255, 255, 0.5)'; // 透明度50% resizeButton.style.border = '1px solid #ccc'; resizeButton.style.padding = '5px'; resizeButton.style.cursor = 'pointer'; resizeButton.addEventListener('click', function() { currentSizeIndex = (currentSizeIndex + 1) % sizes.length; previewVideo.style.width = sizes[currentSizeIndex].width; previewVideo.style.height = sizes[currentSizeIndex].height; }); previewVideo.appendChild(resizeButton); let closeButton = document.createElement('button'); closeButton.textContent = '✕'; closeButton.style.position = 'absolute'; closeButton.style.top = '10px'; closeButton.style.left = '10px'; closeButton.style.zIndex = '1001'; closeButton.style.backgroundColor = 'rgba(255, 255, 255, 0.5)'; // 透明度50% closeButton.style.border = '1px solid #ccc'; closeButton.style.padding = '5px'; closeButton.style.cursor = 'pointer'; closeButton.addEventListener('click', function() { stopPreview(); }); previewVideo.appendChild(closeButton); document.body.appendChild(previewVideo); // プレーヤーを初期化 player = new YT.Player(iframe, { events: { 'onReady': onPlayerReady } }); } function stopPreview() { if (player) { player.stopVideo(); } if (previewVideo) { previewVideo.remove(); previewVideo = null; } } // プレーヤーが準備完了したときの処理 function onPlayerReady(event) { event.target.setVolume(50); // 音量を50に設定 event.target.playVideo(); } })();