video中提取帧图片关键帧

Vedio获取视频帧


浏览器端实现

体验地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- <link rel="stylesheet" type="text/css" href="css/styles.css"> -->
<title>从视频中提取帧</title>
</head>

<body>
<h2>从视频中提取帧</h2>
<p>上传视频并播放您要从中提取帧的部分。</p>

<input id="videoInput" type="file" accept="video/*">
<br /><br />

<video id="video" width="426" height="240" controls muted></video>
<br />
<canvas id="canvas" width="426" height="240"></canvas>

<br /><br />

<button onclick="downloadFrames()">下载视频帧</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.0/jszip.min.js"></script>
<script src="./index.js"></script>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
let videoName;
let frames;
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const inputElement = document.getElementById('videoInput');

// when user inputs video, load it in our video element
inputElement.addEventListener('change', () => {
frames = []; // clear existing frame data
let fileList = inputElement.files;
if(fileList.length > 0) {
videoName = fileList[0].name.split('.')[0];
video.src = URL.createObjectURL(fileList[0]);
video.load();
}
});

const ctx = canvas.getContext('2d');
// when the video is playing draw each frame to canvas
// then encode the canvas as a base64 png
video.addEventListener('play', () => {
function drawFrame() {
if(!video.paused && !video.ended) {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
let img = canvas.toDataURL("image/png");
frames.push(img);
requestAnimationFrame(drawFrame);
}
}
requestAnimationFrame(drawFrame);
});

// download the encoded png files as a zip
function downloadFrames() {
video.pause();
if(frames && frames.length > 0) {
console.log(frames.length + ' frames captured');
let zip = new JSZip();
let zipFilename = videoName + "Frames.zip";

// save one frame for every 60 captures
for(let i = 0; i < frames.length; i += 60) {
zip.file(i + ".png", frames[i].split(',')[1], {base64: true});
}

zip.generateAsync({ type: 'blob' }).then(function (content) {
saveAs(content, zipFilename);
});
}
}