您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays and tracks YouTube subtitles in a floating panel
// ==UserScript== // @name YouTube Subtitle Panel // @namespace https://github.com/YoungerMouse // @version 0.6.8 // @description Displays and tracks YouTube subtitles in a floating panel // @author YoungerMouse // @match https://www.youtube.com/* // @license MIT // @grant none // ==/UserScript== (function () { 'use strict'; // Make original captions selectable const style = document.createElement('style'); style.textContent = ` .caption-visual-line, .captions-text { user-select: text !important; } `; document.head.appendChild(style); // Subtitle panel const panel = document.createElement('div'); Object.assign(panel.style, { position: 'fixed', bottom: '12%', right: '2%', width: '360px', maxHeight: '40%', overflowY: 'auto', background: 'rgba(0,0,0,0.7)', color: 'white', fontSize: '14px', padding: '10px', zIndex: '9999', borderRadius: '8px', whiteSpace: 'pre-wrap', fontFamily: 'sans-serif' }); document.body.appendChild(panel); // Button container const buttonContainer = document.createElement('div'); Object.assign(buttonContainer.style, { position: 'fixed', bottom: '6%', right: '2%', display: 'flex', gap: '8px', zIndex: '9999' }); document.body.appendChild(buttonContainer); // Create buttons function createButton(label) { const btn = document.createElement('button'); btn.textContent = label; Object.assign(btn.style, { padding: '6px 10px', background: '#00B75A', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }); buttonContainer.appendChild(btn); return btn; } // Button order: [Mode, Copy, Clear, Hide] const btnMode = createButton('Manual'); const btnCopy = createButton('Copy'); const btnClear = createButton('Clear'); const btnToggle = createButton('Hide'); let subtitleLines = []; let lastText = ''; let panelVisible = true; let autoMode = false; // Default: Manual btnCopy.onclick = () => { const text = subtitleLines.join('\n'); navigator.clipboard.writeText(text); btnCopy.textContent = 'Copied!'; setTimeout(() => (btnCopy.textContent = 'Copy'), 1500); }; btnClear.onclick = () => { subtitleLines = []; panel.textContent = ''; }; btnToggle.onclick = () => { panelVisible = !panelVisible; panel.style.display = panelVisible ? 'block' : 'none'; btnMode.style.display = panelVisible ? 'inline-block' : 'none'; btnCopy.style.display = panelVisible ? 'inline-block' : 'none'; btnClear.style.display = panelVisible ? 'inline-block' : 'none'; btnToggle.textContent = panelVisible ? 'Hide' : 'Show'; }; btnMode.onclick = () => { autoMode = !autoMode; btnMode.textContent = autoMode ? 'Auto' : 'Manual'; }; function getCurrentSubtitleBlock() { const lines = document.querySelectorAll('.caption-visual-line'); if (autoMode && lines.length >= 1) { return lines[0].textContent.trim(); // Auto: only first line } return Array.from(lines) .map(el => el.textContent.trim()) .filter(Boolean) .join('\n'); } setInterval(() => { const text = getCurrentSubtitleBlock(); if (text && text !== lastText) { lastText = text; subtitleLines.push(text); panel.textContent += text + '\n'; panel.scrollTop = panel.scrollHeight; } }, 300); })();