从视频流中提取每一帧图像
举个例子,选择一个文件,根据这个视频文件,把那些一帧一帧的画面,给做一个图片显示出来。
可以通过以下步骤构建视频帧提取功能:
文件选择交互:
- 在页面中添加文件选择控件
- 为控件绑定change事件监听器
- 当用户选择视频文件后触发处理逻辑
视频帧处理:
- 使用HTML5 Video元素和Canvas API
- 通过视频时间轴逐帧捕获画面
- 将捕获的帧转换为图像数据
const inp = document.querySelector('input[type=file]');
inp.onchange = e => {
const file = e.target.files[0]
capptureFrame(file, 1)
}
function capptureFrame(file, time = 0) {
return {
url: '',
blob: ''
}
}
通过e.target.files[0]
拿到选择的文件。
根据这个选择的文件,来生成某一帧的画面,要写这么一个辅助方法,叫capptureFrame
。
具体实现:
首先,把这个video元素。
接着,跳到这个video元素指定的时间点。
然后,把它画到
canvas
里面。
为什么:
因为,能够得到整个canvas里面画的二进制数据,以及,通过这个数据,生成一些UI和地址。
function capptureFrame(file, time = 0) {
const vdo = document.createElement('video');
vdo.src = URL.createObjectURL(file);
console.log(vdo.src);
}
object url
(它是一个blob协议开头):
通过这样的地址,访问到本地计算机里边的一些资源,直接粘贴到地址栏blob:http://127.0.0.1:5500/f16b2abc-61f1-43d3-a0c8-c36b7e04c20f
,可以直接访问该视频。
一旦网页关闭了,它就会跟着消失了,就失效了。
function capptureFrame(file, time = 0) {
const vdo = document.createElement("video");
vdo.currentTime = time;
vdo.autoplay = true;
vdo.src = URL.createObjectURL(file);
console.log(vdo.src);
}
可能浏览器的自动播放策略会禁止它自动播放,那么自动播放可能会失败。
在浏览器中处理视频自动播放限制的最佳实践如下:给它自动静音,也不需要他的声音。
vdo.muted = true;
画canvas
vdo.oncanplay = () => {
const cvs = document.createElement('canvas');
cvs.width = vdo.videoWidth;
cvs.height = vdo.videoHeight;
const ctx = cvs.getContext('2d');
ctx.drawImage(vdo, 0, 0, cvs.width, cvs.height);
document.body.appendChild(cvs);
}
选择一个文件,看这个视频的第一秒的画面,是不是就画到页面上去了。
把这个canvas里边的东西导出,导出成一个图片地址,以及一个二进制对象。
canvas里边本身就有一个函数叫做toBlob,异步,传一个回调,把这个转换的一个二进制对象:
cvs.toBlob((blob) => {
const url = URL.createObjectURL(blob);
console.log(url);
})
循环前10s
inp.onchange = (e) => {
const file = e.target.files[0];
for (let i = 0; i < 10; i++) {
captureFrame(file, i).then((res) => {
console.log(res);
const img = document.createElement("img");
img.src = res.url;
document.body.appendChild(img);
});
}
};
全部代码
// 文件选择 和 事件处理
const inp = document.querySelector('input[type=file]');
inp.onchange = e => {
const file = e.target.files[0];
captureFrame(file, 1).then(res => {
console.log(res);
});
for (let i = 0; i < 10; i++) {
captureFrame(file, i).then(res => {
const img = document.createElement("img");
img.src = res.url;
document.body.appendChild(img);
});
}
};
// 帧提取函数
function captureFrame(file, time = 0) {
return new Promise((resolve, reject) => {
const vdo = document.createElement("video");
vdo.currentTime = time;
vdo.autoplay = true;
vdo.muted = true;
vdo.src = URL.createObjectURL(file);
vdo.oncanplay = () => {
const cvs = document.createElement("canvas");
cvs.width = vdo.videoWidth;
cvs.height = vdo.videoHeight;
const ctx = cvs.getContext("2d");
ctx.drawImage(vdo, 0, 0, cvs.width, cvs.height);
cvs.toBlob((blob) => {
const url = URL.createObjectURL(blob);
resolve({
url,
blob
});
});
};
});
}
效果
License:
CC BY 4.0