Create thumbnail from video file via file input

JavascriptHtmlVideoThumbnailsVideo Thumbnails

Javascript Problem Overview


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!

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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 */
                );
            });
        });
    });
}

Solution 3 - Javascript

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();

Solution 4 - Javascript

The easiest way to display a thumbnail is using the <video> tag itself.

<video src="http://www.w3schools.com/html/mov_bbb.mp4"></video>

Use #t in the URL, if you want the thumbnail of x seconds.

E.g.:

<video src="http://www.w3schools.com/html/mov_bbb.mp4#t=5"></video>

Make sure that it does not include any attributes like autoplay or controls and it should not have a source tag as a child element.

Solution 5 - Javascript

You can use this function that I've written. You just need to pass the video file to it as an argument. It will return the dataURL of the thumbnail(i.e image preview) of that video. You can modify the return type according to your need.

const generateVideoThumbnail = (file: File) => {
  return new Promise((resolve) => {
    const canvas = document.createElement("canvas");
    const video = document.createElement("video");

    // this is important
    video.autoplay = true;
    video.muted = true;
    video.src = URL.createObjectURL(file);

    video.onloadeddata = () => {
      let ctx = canvas.getContext("2d");

      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;

      ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
      video.pause();
      return resolve(canvas.toDataURL("image/png"));
    };
  });
};

Please keep in mind that this is a async function. So make sure to use it accordingly.

For instance:

const handleFileUpload = async (e) => {
  const thumbnail =  await generateVideoThumbnail(e.target.files[0]);
  console.log(thumbnail)
}

Solution 6 - Javascript

With jQuery Lib you can use my code here. $video is a Video element.This function will return a string

function createPoster($video) {
    //here you can set anytime you want
    $video.currentTime = 5;
    var canvas = document.createElement("canvas");
    canvas.width = 350;
    canvas.height = 200;
    canvas.getContext("2d").drawImage($video, 0, 0, canvas.width, canvas.height);
    return canvas.toDataURL("image/jpeg");;
}

Example usage:

$video.setAttribute("poster", createPoster($video));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionryanView Question on Stackoverflow
Solution 1 - JavascriptGiuView Answer on Stackoverflow
Solution 2 - Javascriptuser1032613View Answer on Stackoverflow
Solution 3 - JavascriptAske ErtmannView Answer on Stackoverflow
Solution 4 - JavascriptReza SaadatiView Answer on Stackoverflow
Solution 5 - JavascriptJoel JaimonView Answer on Stackoverflow
Solution 6 - JavascriptuyghurbegView Answer on Stackoverflow