您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
B站视频截图工具,支援截图按钮、快捷键截图、连拍功能,自定义快捷键、连拍间隔设定、中英菜单切换
当前为
// ==UserScript== // @name Bilibili Video Screenshot Helper // @name:zh-TW Bilibili 影片截圖助手 // @name:zh-CN Bilibili 视频截图助手 // @namespace https://www.tampermonkey.net/ // @version 2.3 // @description Bilibili Video Screenshot Tool – supports screenshot button, hotkey capture, burst mode, customizable hotkeys and burst intervals, with menu language switch between Chinese and English. // @description:zh-TW B站影片截圖工具,支援截圖按鈕、快捷鍵截圖、連拍功能,自定義快捷鍵、連拍間隔設定、中英菜單切換 // @description:zh-CN B站视频截图工具,支援截图按钮、快捷键截图、连拍功能,自定义快捷键、连拍间隔设定、中英菜单切换 // @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 insertScreenshotButton() { const qualityBtn = document.querySelector('.bpx-player-ctrl-quality'); if (!qualityBtn || document.querySelector('.bili-screenshot-btn')) return; 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 插入按鈕 ====== 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; } }); // ====== SPA 跳轉偵測,進入新影片頁時強制刷新 ====== let lastPath = location.pathname; function forceReloadOnVideoPage() { const isVideoPage = /\/video\/BV\w+/.test(location.pathname); if (location.pathname !== lastPath) { lastPath = location.pathname; if (isVideoPage) { location.reload(); } } } (function(history){ const pushState = history.pushState; const replaceState = history.replaceState; history.pushState = function() { pushState.apply(this, arguments); setTimeout(forceReloadOnVideoPage, 100); }; history.replaceState = function() { replaceState.apply(this, arguments); setTimeout(forceReloadOnVideoPage, 100); }; })(window.history); window.addEventListener('popstate', () => setTimeout(forceReloadOnVideoPage, 100)); // ====== 初始化 ====== insertScreenshotButton(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址