视频提取画面帧
刀刀
2/25/2025
0 字
0 分钟
思路
视频提取画面帧主要操作是拿到视频的画面后,把画面画到 canvas
上,canvas
可以拿到文件对象 blob
和 url
。而 canvas
不能直接画一个文件,需要使用 video
这类多媒体元素画到 canvas
内。
所以,整体思路如下:
- 根据选择的文件,放到
video
内 - 定格到某一帧
- 把
video
画到canvas
内 - 导出
工具函数
此时写一个工具函数,获取视频文件和帧,返回一个包含 blob
和 url
的对象。
该函数主要做以下操作:
- 创建一个
video
标签 - 通过
URL.createObjectURL
获取 object url 。以blob:
为前缀,复制粘贴到新的网页打开就能看到视频 - 让
video
定格在某个时间,以及让其自动播放。直接设置自动播放可能会播放失败,因为要考虑到不同浏览器的限制,设置静音播放可以在全部浏览器播放成功 - 画到
canvas
。画的时机要在视频能够开始播放后再画,并且添加一个定时器,否则有可能失败,导致画面帧白屏 - 通过
toBlob
方法转为blob
,return
返回blob
和url
js
const box = ref(null)
const drawVideo = vdo => {
return new Promise(resolve => {
const cvs = document.createElement('canvas')
const ctx = cvs.getContext('2d')
cvs.width = vdo.videoWidth
cvs.height = vdo.videoHeight
ctx.drawImage(vdo, 0, 0, cvs.width, cvs.height)
cvs.toBlob(blob => {
resolve({
blob,
url: URL.createObjectURL(blob)
})
})
})
}
const captureImg = frame => {
const img = document.createElement('img')
img.src = frame
box.value.appendChild(img)
}
/**
* 获取视频画面帧
* @params vdoFile: 视频文件
* @params time: 第几帧
* @return 返回blob和url
*/
const captureFrame = (vdoFile, time = 0) => {
return new Promise(resolve => {
const vdo = document.createElement('video')
vdo.currentTime = time // 视频定格
vdo.muted = true // 静音播放
vdo.autoplay = true // 视频自动播放
vdo.oncanplay = () => {
setTimeout(async () => {
const res = await drawVideo(vdo)
resolve(res)
}, 1000);
}
vdo.src = URL.createObjectURL(vdoFile) // 把object url赋值给video标签的src,blob:为前缀,复制粘贴到新的网页打开就能看到视频
})
}
const onChangeFn = async e => {
if(!e) return
for (let i = 0; i < 10; i++) {
const res = await captureFrame(e, (i + 50) * 1)
captureImg(res.url)
}
}
后续也可以通过循环获取多个画面帧。
拓展
之所以使用 URL.createObjectURL
而不是转为 base64
,是因为如果视频文件过大,要全部转为 base64
的话,会很耗时。