Last active
August 16, 2023 10:08
-
-
Save atwong/49b9e7d911dca0663e23c50c60f28784 to your computer and use it in GitHub Desktop.
Extract Multiple Screenshots Video
This file contains hidden or 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
I will do my rounds, to check following:
lets see