主要参考资源 Manipulating video using canvas
直接访问 截图示例 在线查看效果.
思路步骤
- 监听
input[type=file]
的change
事件, 读取event.target.files
获得视频文件 File - 使用
URL.createObjectURL(file)
创建视频数据 - 创建
video
元素, 视频源使用上面创建的 object URL - 使用
canvas.getContext("2d").drawImage
将视频截图绘画到 canvas 元素上 - 调用
canvas.toDataURL
转成base64图标数据, 供<img />
展示
源码
video.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频截图</title>
</head>
<body>
<div>
<label>
请先选择视频: <input type="file" accept="video/*" />
</label>
<button>点此截屏</button>
</div>
<div>
<h3>Canvas 截图</h3>
<canvas id="screenshot" style="width: 200px; height: 200px;"></canvas>
</div>
<div>
<h3>图片截图</h3>
<img />
</div>
<script src="./video.js"></script>
</body>
</html>
video.js
document.querySelector("input[type=file]").addEventListener("change", e => {
/**
* 添加视频
*/
const video = e.target.files[0];
const ele = document.createElement("video");
ele.controls = true;
ele.style.height = "200px";
ele.style.width = "200px";
const source = document.createElement("source");
source.src = URL.createObjectURL(video);
source.type = video.type;
ele.appendChild(source);
document.body.append(ele);
});
document.querySelector("button").addEventListener("click", () => {
/**
* 截图
*/
const video = document.querySelector("video");
const canvas = document.getElementById("screenshot");
const ctx = canvas.getContext("2d");
ctx.drawImage(video, 0, 0, 200, 200);
const imgData = canvas.toDataURL();
document.querySelector("img").src = imgData;
});
或者选中文件自动截屏
document.querySelector("input[type=file]").addEventListener("change", e => {
/**
* 添加视频
*/
const video = e.target.files[0];
readVideoAlbum({
video: video,
}).then(img => document.querySelector("img").src = img);
});
/**
*
* @param {{video: File}} params
*/
function readVideoAlbum(params) {
return new Promise((resolve, reject) => {
const eleVideo = document.createElement("video");
eleVideo.style.display = "none";
eleVideo.controls = true;
eleVideo.autoplay = false;
eleVideo.muted = true;
eleVideo.playsInline = true;
eleVideo.style.height = "auto";
eleVideo.style.width = "auto";
const source = document.createElement("source");
source.src = URL.createObjectURL(params.video);
source.type = params.video.type;
eleVideo.appendChild(source);
document.body.append(eleVideo);
let canvas;
eleVideo.play()
.then(() => {
canvas = document.createElement("canvas");
canvas.width = eleVideo.videoWidth;
canvas.height = eleVideo.videoHeight;
canvas.style.display = "none";
document.body.append(canvas);
const ctx = canvas.getContext("2d");
if (!ctx) {
throw new Error("canvas.getContext 异常");
}
ctx.drawImage(eleVideo, 0, 0, eleVideo.videoWidth, eleVideo.videoHeight);
const base64 = canvas.toDataURL();
resolve(base64);
eleVideo.pause();
})
.catch(err => reject(err))
.then(() => {
setTimeout(() => {
/**
* 销毁创建的元素
*/
canvas && document.body.removeChild(canvas);
document.body.removeChild(eleVideo);
}, 500);
});
});
}