Skip to main content

使用JS对用户选择视频进行截图

· 3 min read
Alan

主要参考资源 Manipulating video using canvas

直接访问 截图示例 在线查看效果.

思路步骤

  1. 监听input[type=file]change事件, 读取 event.target.files 获得视频文件 File
  2. 使用 URL.createObjectURL(file) 创建视频数据
  3. 创建 video 元素, 视频源使用上面创建的 object URL
  4. 使用 canvas.getContext("2d").drawImage 将视频截图绘画到 canvas 元素上
  5. 调用 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);
});
});
}