Skip to content

Instantly share code, notes, and snippets.

@westc
Created October 12, 2018 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westc/427c3c8012aae7c524b3d4d997b67588 to your computer and use it in GitHub Desktop.
Save westc/427c3c8012aae7c524b3d4d997b67588 to your computer and use it in GitHub Desktop.
Gets the data URIs for the images at specific points within a video (MP4 or MKV).
/**
* Gets one or more images from a video at the given times. Works for MP4s and
* at times MKVs.
* @param {string} path
* URL path to the video.
* @param {Array.<number|Function>|number|Function} times
* If a function it will be passed the duration and the return value will be
* used as the amount of seconds at which to grab the image. If a
* non-negative number this will be used as the amount of seconds at which
* to grab the image. If a negative number this will be used as the amount
* of seconds from the end at which to grab the image. If an array it
* should be an array of numbers and/or functions that will be treated as
* previously mentioned.
* @param {Function} callback
* Once done or when an error occurs this function will be called. The 1st
* argument indicate whether the proccess failed. The 2nd will be an array
* of the data URIs representing the captured image(s). The 3rd will be an
* array corresponding to the array of data URIs indicating the times for
* each in seconds.
*/
function getVideoImages(path, times, callback) {
var hasSeeked,
me = this,
dataURIs = [],
captureTimes = [],
video = document.createElement('video'),
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
video.onloadedmetadata = function () {
times = Object.prototype.toString.call(times) == '[object Array]' ? times.slice() : [times];
tryNextFrame();
};
video.onseeked = function () {
if (!hasSeeked) {
hasSeeked = true;
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
dataURIs.push(canvas.toDataURL());
captureTimes.push(this.currentTime);
tryNextFrame();
}
};
video.onerror = function () {
if (!hasSeeked) {
hasSeeked = true;
callback(false);
collectGarbage();
}
};
function tryNextFrame() {
var time = times.shift();
if (time) {
hasSeeked = false;
if ('function' === typeof time) {
time = time(video.duration);
}
video.currentTime = Math.min(Math.max(0, (time < 0 ? video.duration : 0) + time), video.duration);
}
else {
callback(true, dataURIs, captureTimes);
collectGarbage();
}
}
// garbage collect video
function collectGarbage() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
delete canvas;
delete ctx;
video.removeAttribute('src');
video.load();
delete video;
}
video.src = path;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment