Last active
August 5, 2023 05:21
Star
You must be signed in to star a gist
通用video截图
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name 通用video截图和快捷跳转 | |
// @namespace https://gist.github.com/JiaJiaJiang/736f5a90b55b815a0e9eb6463dd09061 | |
// @version 0.4.3 | |
// @description Alt+鼠标右键点击视频所在区域截图,按下Alt与右键后不松开滚动滚轮可微调时间。ctrl或shift+左右键可以跳过op和ed长度的时间。 | |
// @author JiaJiaJiang | |
// @match http://*/* | |
// @match https://*/* | |
// @grant none | |
// @downloadURL https://gist.github.com/JiaJiaJiang/736f5a90b55b815a0e9eb6463dd09061/raw/commonVideoScreenshot.user.js | |
// @updateURL https://gist.github.com/JiaJiaJiang/736f5a90b55b815a0e9eb6463dd09061/raw/commonVideoScreenshot.user.js | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
let createdBlobURLs = new Set(); | |
const canvas = document.createElement('canvas'); | |
canvas.style = `max-width: 90%; | |
max-height:90%; | |
border: 2px solid #000;`; | |
window.addEventListener('beforeunload', () => { | |
for (let u of createdBlobURLs) { | |
URL.revokeObjectURL(u); | |
} | |
}); | |
async function getImgBlob(v) {//跨域无法获取 | |
console.log('截图', v); | |
canvas.width = v.videoWidth; | |
canvas.height = v.videoHeight; | |
canvas.style['aspect-ratio'] = canvas.width / canvas.height; | |
let ctx = canvas.getContext('2d'); | |
ctx.drawImage(v, 0, 0); | |
try { | |
let blob = await canvas.convertToBlob({ | |
type: "image/jpeg", | |
quality: 1 | |
}); | |
let url = URL.createObjectURL(blob); | |
createdBlobURLs.add(url); | |
window.open(url, "_blank"); | |
} catch (err) { | |
console.log('try show canvas'); | |
const dialog = document.createElement('dialog'); | |
dialog.style = `display: flex;position:fixed;top:0;left:0; | |
justify-content: center;border: 0; | |
max-width: 100vw;max-height: 100vh; | |
align-items: center; | |
width: 100%; | |
height: 100%; | |
background: #000000b4;`; | |
dialog.appendChild(canvas); | |
document.body.appendChild(dialog); | |
dialog.showModal(); | |
dialog.addEventListener('click', ev => { | |
document.body.removeChild(dialog); | |
}); | |
} | |
} | |
let lastVideo = null, toCap = false; | |
window.addEventListener('mousedown', ev => { | |
toCap = false; | |
if (!(ev.button === 2 && ev.altKey)) return; | |
let target = ev.target; | |
let v; | |
if (target.localName === 'video') { | |
v = target; | |
} else {//查找子元素是否有video | |
v = target.querySelector('video'); | |
} | |
if (!v) {//查找父元素是否有子元素是否有video | |
let limit = 5; | |
while (limit--) { | |
target = target.parentNode; | |
if (target === document) break; | |
v = target.querySelector('video'); | |
if (v) { | |
break; | |
} | |
} | |
} | |
if (!v) lastVideo = null; | |
else { | |
lastVideo = v; | |
toCap = true; | |
ev.preventDefault(); | |
ev.stopPropagation(); | |
} | |
}); | |
let emited = false; | |
window.addEventListener('mouseup', ev => capEvent(ev)); | |
window.addEventListener('click', ev => capEvent(ev)); | |
function capEvent(ev) { | |
if (emited || !toCap) return; | |
if (lastVideo) { | |
ev.preventDefault(); | |
ev.stopPropagation(); | |
getImgBlob(lastVideo); | |
requestAnimationFrame(() => { | |
lastVideo.pause(); | |
}); | |
} | |
toCap = false; | |
requestAnimationFrame(() => { emited = false; }) | |
} | |
let lastWheel = 0; | |
window.addEventListener('wheel', ev => { | |
if (toCap && lastVideo) { | |
ev.preventDefault(); | |
ev.stopPropagation(); | |
if (Date.now() - lastWheel < 200) return; | |
lastWheel = Date.now(); | |
lastVideo.currentTime += (ev.deltaY > 0 ? 1 : -1) * 1 / 60; | |
} | |
}, { passive: false }); | |
//快捷跳转 | |
window.addEventListener('keydown', e => { | |
if (!e.code.startsWith('Arrow') || !(e.ctrlKey || e.shiftKey) || e.repeat) return; | |
//寻找目标video | |
const videos = [...document.querySelectorAll('video')].filter(v => v.duration >= 300);//忽略5分钟以下的视频 | |
let video; | |
if (videos.length === 0) return; | |
if (videos.length > 1) { | |
video = videos.filter(v => !v.paused)[0];//多于一个常规视频时选择正在播放的第一个视频 | |
} else { | |
video = videos[0]; | |
} | |
if (!video) return; | |
if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
switch (e.code) { | |
case 'ArrowRight': | |
//播放速度越快,考虑到反应时间,快进的时间应该越少 | |
video.currentTime += (90-(video.playbackRate)*5); break;//预估5秒反应时间 | |
case 'ArrowLeft': | |
video.currentTime -= 90; break; | |
} | |
}) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment