每天学习一个技巧,今天是截取视频的关键帧
主要用到了canvas技术
1.首先准备好html
<body>
<input type="file" name="" id="" /> //上传视频文件
<div class="img"></div> // 存放视频帧图片
<script src="./index.js"></script>
</body>
2.主要函数captureFrame(获取视频关键帧的函数)
参数是视频地址,第几秒
返回一个对象 { blob,url }
function captureFrame(vdoFile, time = 0) {
return new Promise((res) => {
const vdo = document.createElement("video"); // 创建一个video元素
vdo.currentTime = time; // 设置视频的起始时间
vdo.muted = true; // 先静音才能播放,某些浏览器有限制
vdo.autoplay = true; // 因为视频并没有放在页面上,所以并不会一直播放下去
// 在视频加载好预备播放的事件中去画canvas获取图片
vdo.oncanplay = async () => {
const frame = await drawVideo(vdo);
duration = vdo.duration; // 获取视频的总时长
res(frame); // 将获取到的图片信息对象返回
};
// 获取当前文件的一个内存URL
vdo.src = URL.createObjectURL(vdoFile);
});
}
3.主要函数drawVideo(canvas画关键帧(异步))
function drawVideo(vdo) {
return new Promise((res) => {
const cvs = document.createElement("canvas"); // 创建canvas元素
const ctx = cvs.getContext("2d"); // 返回一个canvas渲染的上下文
cvs.width = vdo.videoWidth; // 获取视频的宽度
cvs.height = vdo.videoHeight; // 获取视频的高度
ctx.drawImage(vdo, 0, 0, cvs.width, cvs.height); // 从视频的左上角画满视频的宽高
cvs.toBlob((blob) => {
res({
blob,
url: URL.createObjectURL(blob),
});
});
});
}
4.开始操作
创建全局参数
// 获取页面的input
const ipt = document.querySelector("input[type=file]");
// 获取视频的总时长
let duration = 0;
监听input的change事件
创建图片预览图的函数并转为base64格式
// 创建预览图
function createPreview(frame) {
const img = document.createElement("img");
img.src = frame.url;
document.querySelector(".img").appendChild(img);
img.onclick = () => {
let base64 = imageTobase64(img); // 将图片转为base64格式,方便与后端对接
console.log(base64);
};
}
将图片转为base64格式的函数
// 将图片转为base64
function imageTobase64(img) {
const cvs = document.createElement("canvas");
cvs.width = img.width;
cvs.height = img.height;
const ctx = cvs.getContext("2d");
ctx.drawImage(img, 0, 0, cvs.width, cvs.height);
const ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
let dataUrl = cvs.toDataURL("image/jpeg" + ext);
return dataUrl;
}
input的change变化触发
ipt.onchange = async (e) => {
const file = e.target.files[0];
const frame = await captureFrame(file); // 这一步主要是先获取视频的总时长
for (let i = 1; i < duration; i++) { // 然后在从下一秒开始
const frame = await captureFrame(file, i);
createPreview(frame);
}
};