Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
March 27, 2022 04:10 am GMT

Video thumbnails generate with vanilla JS, ReactJS. Like YouTube

Have you ever needed where the user uploads the video and has the option to select a thumbnail? if yes keep reading.

Recently I needed to create a service in one of my projects where users will upload a video and can select a thumbnail of that video, and I needed to generate multiple thumbnails from the different timeframes of video. So the user can select one of the thumbnail from the given

something like this [can't upload the original screen]

Video thumbnails generate with vanilla JS. Like YouTube

I search for JS libraries which can do this for me but ended up creating my own NPM package.
video-thumbnails-generator
Contributions are more than welcome, I have already added a roadmap in the Readme.md.

But first lets see how its working behind the scene.

Index.js The Driver

// convert image to object part instead of base64 for better performance// https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURLexport const importFileandPreview = (file, revoke) => {    return new Promise((resolve, reject) => {        window.URL = window.URL || window.webkitURL;        let preview = window.URL.createObjectURL(file);        // remove reference        if (revoke) {            window.URL.revokeObjectURL(preview);        }        setTimeout(() => {            resolve(preview);        }, 100);    });}/** * * @param videoFile {FIle} // the video file * @param numberOfThumbnails {number} //number of thumbnails you want to generate * @returns {string[]} // an array of base64 thumbnails images * * @abstract * Idea taken from - https://codepen.io/aertmann/pen/mrVaPx * The original functionality of getVideoThumbnail() function is customized as per working code * If it didn't work in future then replace it with about links working example */export const generateVideoThumbnails = async (videoFile, numberOfThumbnails) => {    let thumbnail = [];    let fractions = [];    return new Promise(async (resolve, reject) => {        if (!videoFile.type?.includes("video")) reject("not a valid video file");        await getVideoDuration(videoFile).then(async (duration) => {            // divide the video timing into particular timestamps in respective to number of thumbnails            // ex if time is 10 and numOfthumbnails is 4 then result will be -> 0, 2.5, 5, 7.5 ,10            // we will use this timestamp to take snapshots            for (let i = 0; i <= duration; i += duration / numberOfThumbnails) {                fractions.push(Math.floor(i));            }            // the array of promises            let promiseArray = fractions.map((time) => {                return getVideoThumbnail(videoFile, time)            })            // console.log('promiseArray', promiseArray)            // console.log('duration', duration)            // console.log('fractions', fractions)            await Promise.all(promiseArray).then((res) => {                res.forEach((res) => {                    // console.log('res', res.slice(0,8))                    thumbnail.push(res);                });                // console.log('thumbnail', thumbnail)                resolve(thumbnail);            }).catch((err) => {                console.error(err)            }).finally((res) => {                console.log(res);                resolve(thumbnail);            })        });        reject("something went wront");    });};const getVideoThumbnail = (file, videoTimeInSeconds) => {    return new Promise((resolve, reject) => {        if (file.type.match("video")) {            importFileandPreview(file).then((urlOfFIle) => {                var video = document.createElement("video");                var timeupdate = function () {                    if (snapImage()) {                        video.removeEventListener("timeupdate", timeupdate);                        video.pause();                    }                };                video.addEventListener("loadeddata", function () {                    if (snapImage()) {                        video.removeEventListener("timeupdate", timeupdate);                    }                });                var snapImage = function () {                    var canvas = document.createElement("canvas");                    canvas.width = video.videoWidth;                    canvas.height = video.videoHeight;                    canvas.getContext("2d").drawImage(video, 0, 0, canvas.width, canvas.height);                    var image = canvas.toDataURL();                    var success = image.length > 100000;                    if (success) {                        URL.revokeObjectURL(urlOfFIle);                        resolve(image);                    }                    return success;                };                video.addEventListener("timeupdate", timeupdate);                video.preload = "metadata";                video.src = urlOfFIle;                // Load video in Safari / IE11                video.muted = true;                video.playsInline = true;                video.currentTime = videoTimeInSeconds;                video.play();            });        } else {            reject("file not valid");        }    });};/** * * @param videoFile {File} * @returns {number} the duration of video in seconds */export const getVideoDuration = (videoFile)=> {    return new Promise((resolve, reject) => {        if (videoFile) {            if (videoFile.type.match("video")) {                importFileandPreview(videoFile).then((url) => {                    let video = document.createElement("video");                    video.addEventListener("loadeddata", function () {                        resolve(video.duration);                    });                    video.preload = "metadata";                    video.src = url;                    // Load video in Safari / IE11                    video.muted = true;                    video.playsInline = true;                    video.play();                    //  window.URL.revokeObjectURL(url);                });            }        } else {            reject(0);        }    });};

Explanations

importFileandPreview()

/*** This function will take an File object and will convert it* into windowObjectURI which look something like this - * blob:http://localhost/2d7b2c97-02f3-4e7d-a6c1-d04746c27730*/export const importFileandPreview = (file, revoke) => {    return new Promise((resolve, reject) => {       //@todo - your logic here    });}

getVideoDuration()

/** * @abbrivation This function takes a video File object as an  * input and returns the duration of that video. * * @param videoFile {File} * @returns {number} the duration of video in seconds */export const getVideoDuration = (videoFile)=> {    return new Promise((resolve, reject) => {        if (videoFile) {           resolve(duration);        } else {            reject(0);        }    });};

getVideoThumbnail()

/*** @abbrivation * This function takes a video File Object and the time where we* need a snapshot of video screen.* It will return a snapshot of the video at the given time* in `base64` format.** @param {File} file * @param {number} videoTimeInSeconds * @returns string // base64Image */const getVideoThumbnail = (file, videoTimeInSeconds) => {    return new Promise((resolve, reject) => {        if (file.type.match("video")) {            resolve(thumbnail); //base64 image        } else {            reject("file not valid");        }    });};

generateVideoThumbnails()

/** * This functin will take two input video File and Number * And It will generate that many thumbnails. * * @param videoFile {FIle} // the video file * @param numberOfThumbnails {number} //number of thumbnails you want to generate * @returns {string[]} // an array of base64 thumbnails images * * @abstract * Idea taken from - https://codepen.io/aertmann/pen/mrVaPx * The original functionality of getVideoThumbnail() function is customized as per working code * If it didn't work in future then replace it with about links working example */export const generateVideoThumbnails = async (videoFile, numberOfThumbnails) => {    let thumbnail = [];    let fractions = [];    return new Promise(async (resolve, reject) => {        if (!videoFile.type?.includes("video")) reject("not a valid video file");            // first we get video duration            // then we calculate how many thumbnails to generate            // we cann generateThumbnail() function that many times            // then we resolve all those promises and return result.            await Promise.all(promiseArray).then((res) => {                res.forEach((res) => {                    thumbnail.push(res);                });                resolve(thumbnail);            }).catch((err) => {                console.error(err)            }).finally((res) => {                resolve(thumbnail);            })        });        reject("something went wrong");    });};

See it in action - Live Demo.

Video thumbnails generate with vanilla JS. Like YouTube

Hope you enjoyed it reading. Do not forget share of hit that heart icon see you soon with new material .


Original Link: https://dev.to/rajeshroyal/video-thumbnails-generate-with-vanilla-js-reactjs-like-youtube-3ok8

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To