您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
B站视频截图工具,支援截图按钮、快捷键截图、连拍功能,自定义快捷键、连拍间隔设定、一键切换全屏、VX链结复制按钮、中英菜单切换
当前为
// ==UserScript== // @name Bilibili Video Screenshot Helper & VXBilibili Link Copy Button // @name:zh-TW Bilibili 影片截圖助手 & VXBilibili鏈結複製按鈕 // @name:zh-CN Bilibili 视频截图助手 & VXBilibili链结复制按钮 // @namespace https://www.tampermonkey.net/ // @version 2.8 // @description Bilibili video screenshot tool supporting screenshot buttons, shortcut key screenshots, burst shooting, customizable shortcut keys, burst interval settings, one-click fullscreen toggle, VX link copy button, and Chinese-English menu switching. // @description:zh-TW B站影片截圖工具,支援截圖按鈕、快捷鍵截圖、連拍功能,自定義快捷鍵、連拍間隔設定、一鍵切換全屏、VX鏈結複製按鈕、中英菜單切換 // @description:zh-CN B站视频截图工具,支援截图按钮、快捷键截图、连拍功能,自定义快捷键、连拍间隔设定、一键切换全屏、VX链结复制按钮、中英菜单切换 // @author ChatGPT // @match https://www.bilibili.com/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @run-at document- // @license MIT // ==/UserScript== (function () { 'use strict'; // ====== 預設設定 ====== const DEFAULTS = { key: 'S', interval: 1000, minInterval: 100, lang: 'EN', lockKey: 'bili_screenshot_prompt_lock' }; // ====== 語言包 ====== const LANGS = { EN: { screenshot: 'Screenshot', keySetting: key => `Set Screenshot Key (Current: ${key})`, intervalSetting: val => `Set Burst Interval (Current: ${val}ms)`, langSwitch: 'Switch to 中文', keyPrompt: 'Enter new key (A-Z)', intervalPrompt: 'Enter new interval in ms (>= 100)' }, ZH: { screenshot: '截圖', keySetting: key => `設定截圖快捷鍵(目前:${key})`, intervalSetting: val => `設定連拍間隔(目前:${val} 毫秒)`, langSwitch: '切換到 English', keyPrompt: '輸入新快捷鍵(A-Z)', intervalPrompt: '輸入新的連拍間隔(最小 100ms)' } }; // ====== 狀態管理 ====== let lang = GM_getValue('lang', DEFAULTS.lang); let hotkey = GM_getValue('hotkey', DEFAULTS.key); let interval = GM_getValue('interval', DEFAULTS.interval); function getLangPack() { return LANGS[lang]; } // ====== 設定選單註冊 ====== function safePrompt(action) { if (window.top !== window.self) return; if (sessionStorage.getItem(DEFAULTS.lockKey) === '1') return; sessionStorage.setItem(DEFAULTS.lockKey, '1'); try { action(); } finally { sessionStorage.removeItem(DEFAULTS.lockKey); } } GM_registerMenuCommand(getLangPack().keySetting(hotkey), () => { safePrompt(() => { const input = prompt(getLangPack().keyPrompt); if (input && /^[a-zA-Z]$/.test(input)) { const newKey = input.toUpperCase(); if (newKey !== hotkey) { GM_setValue('hotkey', newKey); location.reload(); } } }); }); GM_registerMenuCommand(getLangPack().intervalSetting(interval), () => { safePrompt(() => { const input = prompt(getLangPack().intervalPrompt); const val = parseInt(input, 10); if (!isNaN(val) && val >= DEFAULTS.minInterval && val !== interval) { GM_setValue('interval', val); location.reload(); } }); }); GM_registerMenuCommand(getLangPack().langSwitch, () => { safePrompt(() => { const newLang = lang === 'EN' ? 'ZH' : 'EN'; GM_setValue('lang', newLang); location.reload(); }); }); // ====== 取得影片標題 ====== function getVideoTitle() { // 新播放器 let title = document.querySelector('h1[data-v-1c684a5a]')?.innerText || document.querySelector('h1.video-title')?.innerText || document.querySelector('h1')?.innerText; // 備用:<title> if (!title) { title = document.title.replace(/_.*$/, '').trim(); } // 過濾非法檔名字元 if (title) { title = title.replace(/[\\/:*?"<>|]/g, '_').replace(/\s+/g, '_'); } else { title = 'UnknownTitle'; } return title; } // ====== 截圖邏輯 ====== function takeScreenshot() { const video = document.querySelector('video'); const match = location.pathname.match(/\/video\/(BV\w+)/); if (!match || !video || video.paused) return; const canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); const pad = (n, len = 2) => n.toString().padStart(len, '0'); const padMs = n => pad(n, 3); const bvId = match[1]; const t = video.currentTime; const h = pad(Math.floor(t / 3600)); const m = pad(Math.floor((t % 3600) / 60)); const s = pad(Math.floor(t % 60)); const ms = padMs(Math.floor((t * 1000) % 1000)); const res = `${canvas.width}x${canvas.height}`; const title = getVideoTitle(); // 命名規則:影片標題_小時_分鐘_秒_毫秒_BV號_解析度 const filename = `${title}_${h}_${m}_${s}_${ms}_${bvId}_${res}.png`; canvas.toBlob(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); setTimeout(() => URL.revokeObjectURL(url), 100); }, 'image/png'); } // ====== 新增:簡易通知函式 ====== function showNotification(msg) { const notif = document.createElement('div'); notif.textContent = msg; Object.assign(notif.style, { position: 'fixed', bottom: '20px', right: '20px', backgroundColor: 'rgba(0,0,0,0.75)', color: 'white', padding: '8px 12px', borderRadius: '4px', fontSize: '14px', zIndex: 9999, opacity: 0, transition: 'opacity 0.3s ease' }); document.body.appendChild(notif); // 觸發 CSS 過渡效果 requestAnimationFrame(() => { notif.style.opacity = 1; }); setTimeout(() => { notif.style.opacity = 0; setTimeout(() => document.body.removeChild(notif), 300); }, 1500); } // ====== 插入截圖與複製網址按鈕 ====== function insertScreenshotButton() { const qualityBtn = document.querySelector('.bpx-player-ctrl-quality'); if (!qualityBtn || document.querySelector('.bili-screenshot-btn')) return; // 插入複製網址按鈕(放在截圖按鈕左邊) const copyBtn = document.createElement('div'); copyBtn.className = 'bpx-player-ctrl-btn bili-copylink-btn'; Object.assign(copyBtn.style, { display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', fontSize: '18px', marginRight: '6px' }); copyBtn.title = 'Copy Modified URL'; copyBtn.innerHTML = '🔗'; copyBtn.addEventListener('click', () => { let url = location.href; url = url.replace(/^https:\/\/(www\.)?bilibili\.com/, 'https://www.vxbilibili.com'); url = url.replace(/^https:\/\/(www\.)?b23\.tv/, 'https://vxb23.tv'); navigator.clipboard.writeText(url).then(() => { showNotification('✅ URL copied!'); console.log('✅ URL copied:', url); }).catch(err => { showNotification('❌ Copy failed!'); console.error('❌ Copy failed:', err); }); }); qualityBtn.parentNode.insertBefore(copyBtn, qualityBtn); // 插入截圖按鈕 const btn = document.createElement('div'); btn.className = 'bpx-player-ctrl-btn bili-screenshot-btn'; Object.assign(btn.style, { display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', fontSize: '18px', marginRight: '6px' }); btn.title = getLangPack().screenshot; btn.innerHTML = '📸'; btn.addEventListener('click', takeScreenshot); qualityBtn.parentNode.insertBefore(btn, qualityBtn); } // ====== 監聽 DOM 變動(SPA 支援) ====== const observer = new MutationObserver(() => { insertScreenshotButton(); // 動態更新截圖按鈕 title const btn = document.querySelector('.bili-screenshot-btn'); if (btn) btn.title = getLangPack().screenshot; }); observer.observe(document.body, { childList: true, subtree: true }); // ====== 快捷鍵與連拍功能 ====== let holdTimer = null; document.addEventListener('keydown', e => { if (e.repeat) return; if (['INPUT', 'TEXTAREA'].includes(e.target.tagName) || e.target.isContentEditable) return; hotkey = GM_getValue('hotkey', DEFAULTS.key); interval = GM_getValue('interval', DEFAULTS.interval); if (e.key.toUpperCase() === hotkey && !holdTimer) { takeScreenshot(); holdTimer = setInterval(takeScreenshot, interval); } }); document.addEventListener('keyup', e => { hotkey = GM_getValue('hotkey', DEFAULTS.key); if (e.key.toUpperCase() === hotkey && holdTimer) { clearInterval(holdTimer); holdTimer = null; } }); // ====== 快捷鍵:切換網頁全螢幕 ====== document.addEventListener('keydown', e => { if (e.key === '`' && !e.repeat) { if (['INPUT', 'TEXTAREA'].includes(e.target.tagName) || e.target.isContentEditable) return; const webFullBtn = document.querySelector('.bpx-player-ctrl-web'); if (webFullBtn) webFullBtn.click(); } }); // ====== SPA 路徑變化偵測(不 reload,只更新語言包) ====== let lastPath = location.pathname; function onPathChange() { if (location.pathname !== lastPath) { lastPath = location.pathname; setTimeout(() => { const btn = document.querySelector('.bili-screenshot-btn'); if (btn) btn.title = getLangPack().screenshot; }, 500); } } (function(history){ const pushState = history.pushState; const replaceState = history.replaceState; history.pushState = function() { pushState.apply(this, arguments); setTimeout(onPathChange, 100); }; history.replaceState = function() { replaceState.apply(this, arguments); setTimeout(onPathChange, 100); }; })(window.history); window.addEventListener('popstate', () => setTimeout(onPathChange, 100)); // ====== 初始化 ====== insertScreenshotButton(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址