您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Captures the current video frame on YouTube
// ==UserScript== // @name YouTube Screenshot (Mobile) // @namespace https://greasyfork.org/en/scripts/551134-youtube-screenshot-mobile // @version 1.0 // @description Captures the current video frame on YouTube // @author Adam Jensen // @license MIT // @match *://m.youtube.com/* // @grant GM_download // @run-at document-idle // ==/UserScript== (function() { 'use strict'; const captureButton = document.createElement('button'); captureButton.id = 'capture-frame-button-flotante'; captureButton.innerText = '📸'; captureButton.style.cssText = ` position: fixed; bottom: 120px; right: 20px; z-index: 9999; padding: 10px; background-color: #0088AA; color: #fff; border: none; border-radius: 50%; width: 45px; height: 45px; font-size: 20px; line-height: 0; box-shadow: 0 3px 6px rgba(0,0,0,0.4); cursor: pointer; display: none; `; document.body.appendChild(captureButton); const isVideoPage = () => { return window.location.pathname === '/watch' && window.location.search.includes('v='); }; const getVideoElement = () => { return document.querySelector('video'); }; const getVideoId = () => { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('v'); }; function captureFrame() { const video = getVideoElement(); if (!video) { alert('Video element not found.'); return; } const wasPaused = video.paused; video.pause(); const canvas = document.createElement('canvas'); canvas.width = video.videoWidth || video.clientWidth; canvas.height = video.videoHeight || video.clientHeight; const ctx = canvas.getContext('2d'); try { ctx.drawImage(video, 0, 0, canvas.width, canvas.height); } catch (e) { console.error('Error drawing video to canvas (possible CORS issue):', e); alert('Capture error. The video might be CORS protected.'); if (!wasPaused) video.play(); return; } const dataURL = canvas.toDataURL('image/png'); const videoId = getVideoId() || 'UNKNOWN_ID'; const now = new Date(); // Format: YYYYMMDD const datePart = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`; // Format: HHMMSS const timePart = `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`; const filename = `YouTube_Frame_${videoId}_${datePart}_${timePart}.png`; if (typeof GM_download === 'function') { GM_download({ url: dataURL, name: filename, saveAs: true }); console.log('Capture saved using GM_download.'); } else { const a = document.createElement('a'); a.href = dataURL; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); console.log('Capture downloaded using fallback.'); } if (!wasPaused) { video.play(); } } captureButton.addEventListener('click', captureFrame); const updateButtonVisibility = () => { const shouldShow = isVideoPage() && getVideoElement(); captureButton.style.display = shouldShow ? 'block' : 'none'; const video = getVideoElement(); if (video && (video.webkitDisplayingFullscreen || video.mozDisplayingFullscreen || document.fullscreenElement)) { captureButton.style.bottom = '20px'; } else { captureButton.style.bottom = '120px'; } }; setInterval(updateButtonVisibility, 500); updateButtonVisibility(); })();