在这样一个图像化极其重要的时代,从视频中提取精彩瞬间,即视频帧截图的技术,已成为前端开发中的一个亮点。JavaScript作为网页动态效果和交互的主力军,其在视频处理领域能力逐渐被挖掘和重视,尤其是视频帧截图技术的应用,为网站和应用程序提供了更为丰富和直观的用户体验。
大体为以下流程:
选择视频文件定格帧
选择本地视频文件
<input type="file">
const input = document.querySelector('input');
input.onchange = async (e) => {
const file = e.target.files[0];
console.log(file);
}
创建一个video标签,把视频文件放到video标签中。使用 createObjectURL 方法把视频文件对象转为一个url。
const video = document.createElement("video");
video.src = URL.createObjectURL(file);
// 设置视频自动播放
video.autoplay = true;
// 设置视频播放的时间点
video.currentTime = 10;
使用 createObjectURL
创建的URL是一个blob:开头的临时路径,这个路径可以在浏览器中直接访问,访问到的内容就是上传的视频文件。当页面关闭后,此路径也随之失效。
通过 currentTime
设置需要截图的时间点,由于创建的video标签未加到页面中,所以这里设置了自动播放后,不会继续播放10s后的内容,而是停留在10s的位置。
绘制视频帧
现在视频停留在了指定帧的位置,接下来就通过 canvas来绘制当前帧。
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = vdo.videoWidth;
canvas.height = vdo.videoHeight;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
document.body.appendChild(canvas);
转为图片地址
将canvas内容转为一个可用img标签展示的url地址,这个过程需要两步:
- 使用
toBlob
方法创造一个Blob对象 - 使用
createObjectURL
方法把对象转为可访问的URL
function drawVideo(vdo) {
return new Promise((resolve) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = vdo.videoWidth;
canvas.height = vdo.videoHeight;
ctx.drawImage(vdo, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => {
resolve({
blob,
url: URL.createObjectURL(blob)
});
})
})
}
由于 toBlob 是采用回调函数的方式调用,所以封装drawVideo 方法返回为一个promise。
截图全流程
当video标签设置url后,不能马上截图,视频加载需要一个过程,要等视频可以播放后再截图。
video.oncanplay = async () => {
const frame = await drawVideo(video);
}
封装完整的截图方法,由于oncanplay
同样是一个异步方法,这里也需要返回一个promise
function captureFrame(file, time) {
return new Promise((resolve) => {
const video = document.createElement("video");
video.autoplay = true;
video.currentTime = time;
video.src = URL.createObjectURL(file);
video.oncanplay = async () => {
const frame = await drawVideo(video);
resolve(frame);
}
})
}
获取视频时长,按照每1秒的间隔截一张图
const video = document.createElement("video");
video.src = URL.createObjectURL(file);
// 视频加载完成后,才能获取到视频的时长
video.onloadedmetadata = async () => {
for (let index = 0; index < video.duration; index++) {
const frame = await captureFrame(file, index);
// 将截图加入到页面中展示
const img = document.createElement("img");
img.src = frame.url;
img.style.width = "100px";
document.body.appendChild(img);
}
};
尽管视频帧截图技术带来了许多便利,但在实际应用过程中也面临着一些挑战:
- 性能问题:处理大量或高分辨率视频时的性能消耗较大,可能影响页面加载速度和用户体验。解决方案包括优化图片尺寸、使用异步加载技术、以及在服务器端进行视频处理等。
- 浏览器兼容性:不同浏览器对视频解码和渲染的支持程度不同,可能导致在某些浏览器上无法正确显示视频帧截图。解决这一问题的方法包括使用广泛支持的编解码器和格式,以及提供替代的媒体格式。
- 用户体验:如何让用户方便快捷地选择和保存截图是一个需要解决的问题。提供直观的用户界面和明确的操作指导是提升用户体验的关键。
随着前端技术的不断进步,未来视频帧截图技术将变得更加高效和用户友好。Web Assembly和FFmpeg等技术的发展有望进一步提升前端处理视频的能力,使得视频帧截图更加迅速和精确。
关注公众号【前端筱园】,回复“视频帧截图”获取本案例源码及素材
写在最后
欢迎访问我的个人网站:www.dengzhanyong.com
欢迎加入前端筱园交流群:
关注我的公众号【前端筱园】,不错过每一篇推送