Created
October 12, 2018 14:36
-
-
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).
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
/** | |
* 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