Skip to content

Instantly share code, notes, and snippets.

@samueleastdev
Forked from atwong/extractvideo.js
Created July 18, 2019 14:30
Show Gist options
  • Save samueleastdev/9a694564f513a0c480ba1d22db86916d to your computer and use it in GitHub Desktop.
Save samueleastdev/9a694564f513a0c480ba1d22db86916d to your computer and use it in GitHub Desktop.
Extract Multiple Screenshots Video
/*
* Extract multiple screenshots/frames from a video URL
* Params
* - vidURL : video URL
* - frOffsets : array of timestamps
* - frameWidth : screenshot width (default: video width)
* Returns
* - frames: object with offset => {imgUrl, blob}
*
* An multiple-frame extension of http://cwestblog.com/2017/05/03/javascript-snippet-get-video-frame-as-an-image/
* In this version, video & canvas elements are reused to extract multiple screenshots. Note, video seeks must
* occur serially, hence use of async/await.
*/
function extractVideoFrames(vidUrl, frOffsets, frameWidth) {
function extractFrame(video, canvas, offset) {
return new Promise((resolve, reject) => {
video.onseeked = event => {
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob(blob => {
resolve({offset: offset, imgUrl: canvas.toDataURL() , blob: blob});
}, "image/png");
};
video.currentTime = offset;
});
};
async function serialExtractFrames(video, canvas, offsets) {
var frames = {};
var lastP = null;
for (var offset of offsets) {
if (offset < video.duration) {
if (lastP) {
var f = await lastP
frames[f.offset] = f;
}
lastP = extractFrame(video, canvas, offset);
}
}
if (lastP) {
var f = await lastP;
frames[f.offset] = f;
lastP = null;
}
return frames;
};
return new Promise((resolve, reject) => {
var vvid = document.createElement("video");
var vcnv = document.createElement("canvas");
vvid.onloadedmetadata = event => {
var aspect_ratio = vvid.videoWidth/vvid.videoHeight;
vcnv.width = frameWidth !== undefined ? frameWidth : vvid.videoWidth;
vcnv.height = vcnv.width/aspect_ratio;
if (vvid.duration) {
serialExtractFrames(vvid, vcnv, frOffsets).then(resp => {
resolve(resp);
})
}
}
vvid.src = vidUrl;
});
};
export default extractVideoFrames;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment