Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create thumbnail from video file via file input

I am attempting to create a thumbnail preview from a video file (mp4,3gp) from a form input type='file'. Many have said that this can be done server side only. I find this hard to believe since I just recently came across this Fiddle using HTML5 Canvas and Javascript.

Thumbnail Fiddle

The only problem is this requires the video to be present and the user to click play before they click a button to capture the thumbnail. I am wondering if there is a way to get the same results without the player being present and user clicking the button. For example: User click on file upload and selects video file and then thumbnail is generated. Any help/thoughts are welcome!

like image 611
ryan Avatar asked May 13 '14 20:05

ryan


People also ask

How do I get a video thumbnail in HTML?

Approach: Sometimes the user wants to display a specific image of his choice as the thumbnail of the video. This can be simply done by using the poster attribute. All you have to do is create a poster attribute in the video tag and place the URL of the thumbnail image in it.


3 Answers

Canvas.drawImage must be based on html content.

source

here is a simplier jsfiddle

//and code
function capture(){
    var canvas = document.getElementById('canvas');
    var video = document.getElementById('video');
    canvas.getContext('2d').drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
}

The advantage of this solution is that you can select the thumbnail you want based on the time of the video.

like image 133
Giu Avatar answered Oct 21 '22 14:10

Giu


Recently needed this and did quite some testing and boiling it down to the bare minimum, see https://codepen.io/aertmann/pen/mAVaPx

There are some limitations where it works, but fairly good browser support currently: Chrome, Firefox, Safari, Opera, IE10, IE11, Android (Chrome), iOS Safari (10+).

 video.preload = 'metadata';
 video.src = url;
 // Load video in Safari / IE11
 video.muted = true;
 video.playsInline = true;
 video.play();
like image 26
Aske Ertmann Avatar answered Oct 21 '22 12:10

Aske Ertmann


Recently needed this so I wrote a function, to take in a video file and a desired timestamp, and return an image blob at that time of the video.

Sample Usage:

try {
    // get the frame at 1.5 seconds of the video file
    const cover = await getVideoCover(file, 1.5);
    // print out the result image blob
    console.log(cover);
} catch (ex) {
    console.log("ERROR: ", ex);
}

Function:

function getVideoCover(file, seekTo = 0.0) {
    console.log("getting video cover for file: ", file);
    return new Promise((resolve, reject) => {
        // load the file to a video player
        const videoPlayer = document.createElement('video');
        videoPlayer.setAttribute('src', URL.createObjectURL(file));
        videoPlayer.load();
        videoPlayer.addEventListener('error', (ex) => {
            reject("error when loading video file", ex);
        });
        // load metadata of the video to get video duration and dimensions
        videoPlayer.addEventListener('loadedmetadata', () => {
            // seek to user defined timestamp (in seconds) if possible
            if (videoPlayer.duration < seekTo) {
                reject("video is too short.");
                return;
            }
            // delay seeking or else 'seeked' event won't fire on Safari
            setTimeout(() => {
              videoPlayer.currentTime = seekTo;
            }, 200);
            // extract video thumbnail once seeking is complete
            videoPlayer.addEventListener('seeked', () => {
                console.log('video is now paused at %ss.', seekTo);
                // define a canvas to have the same dimension as the video
                const canvas = document.createElement("canvas");
                canvas.width = videoPlayer.videoWidth;
                canvas.height = videoPlayer.videoHeight;
                // draw the video frame to canvas
                const ctx = canvas.getContext("2d");
                ctx.drawImage(videoPlayer, 0, 0, canvas.width, canvas.height);
                // return the canvas image as a blob
                ctx.canvas.toBlob(
                    blob => {
                        resolve(blob);
                    },
                    "image/jpeg",
                    0.75 /* quality */
                );
            });
        });
    });
}
like image 36
user1032613 Avatar answered Oct 21 '22 14:10

user1032613