-
-
Save samueleastdev/9a694564f513a0c480ba1d22db86916d to your computer and use it in GitHub Desktop.
Extract Multiple Screenshots Video
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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