-
-
Save bonsi/28faa641acd6135d26dc to your computer and use it in GitHub Desktop.
Generate thumbnails from video files using HTML5's video tag and canvas
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
<?php | |
//where you want your thumbnails to go | |
$thumbs_dir = 'uploads/thumbs/'; | |
//this should be an array of video paths | |
$videos = array(); | |
if( $_POST["name"] ){ | |
// Grab the MIME type and the data with a regex for convenience | |
if (!preg_match('/data:([^;]*);base64,(.*)/', $_POST['data'], $matches)) { | |
die("error"); | |
} | |
// Decode the data | |
$data = $matches[2]; | |
$data = str_replace(' ','+',$data); | |
$data = base64_decode($data); | |
file_put_contents($thumbs_dir.$file, $data); | |
print 'done '.$name; | |
exit; | |
} | |
?> | |
<video id="video" src="" onerror="failed(event)" controls="controls" preload="none"></video> | |
<script> | |
var videos = <?=json_encode($videos);?>; | |
var index = 0; | |
var video = document.getElementById('video'); | |
video.addEventListener('canplay', function() { | |
this.currentTime = this.duration / 2; | |
}, false); | |
video.addEventListener('seeked', function() { | |
getThumb(); | |
}, false); | |
function nextVideo(){ | |
if(videos[index]){ | |
video.src = '/uploads/'+videos[index]; | |
console.log(index); | |
console.log('loading: '+video.src); | |
video.load(); | |
index++; | |
}else{ | |
console.log('done'); | |
} | |
} | |
function getThumb(){ | |
var filename = video.src; | |
var w = video.videoWidth;//video.videoWidth * scaleFactor; | |
var h = video.videoHeight;//video.videoHeight * scaleFactor; | |
var canvas = document.createElement('canvas'); | |
canvas.width = w; | |
canvas.height = h; | |
var ctx = canvas.getContext('2d'); | |
ctx.drawImage(video, 0, 0, w, h); | |
//document.body.appendChild(canvas); | |
var data = canvas.toDataURL("image/jpg"); | |
//send to php script | |
var xmlhttp = new XMLHttpRequest; | |
xmlhttp.onreadystatechange = function(){ | |
if (xmlhttp.readyState==4 && xmlhttp.status==200){ | |
console.log('saved'); | |
nextVideo(); | |
} | |
} | |
console.log('saving'); | |
xmlhttp.open("POST", location.href, true); | |
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); | |
xmlhttp.send('name='+encodeURIComponent(filename)+'&data='+data); | |
} | |
function failed(e) { | |
// video playback failed - show a message saying why | |
switch (e.target.error.code) { | |
case e.target.error.MEDIA_ERR_ABORTED: | |
console.log('You aborted the video playback.'); | |
break; | |
case e.target.error.MEDIA_ERR_NETWORK: | |
console.log('A network error caused the video download to fail part-way.'); | |
break; | |
case e.target.error.MEDIA_ERR_DECODE: | |
console.log('The video playback was aborted due to a corruption problem or because the video used features your browser did not support.'); | |
break; | |
case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED: | |
console.log('The video could not be loaded, either because the server or network failed or because the format is not supported.'); | |
break; | |
default: | |
console.log('An unknown error occurred.'); | |
break; | |
} | |
nextVideo(); | |
} | |
//let's go | |
nextVideo(); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@unalignedcoder: In case you're still looking to use this script: the POST URL used above is the same as the page this snippet is included. All parameters (the filename + thumbnail data) are automatically added on line 80 so the only thing left to do is to catch those parameters on the server and save the thumbnail data to a file.
On a side note: I've never gotten as far as to put this script to use. I've abandoned this approach in favor of a more server-side solution: using a videoplayer which supports extracting the exact timecode of the frame to be thumbnailed and then sending that timecode to the server where I use ffmpeg to create the thumbnail. This approach allows for a much wider range of video formats to be thumbnailed as opposed to HTML video which supports only a few formats.