In various web applications related to video content, you may be required to develop this feature of generating thumbnails from uploaded videos.
This can be achieved using various libraries available out there or you can try to make one for yourself.
In this article, I have shared the way to make it custom without any libraries.
This may not be the best approach but it may give you the general direction of approaching this problem.
First, create your next app using the below command.
npx create-next-app@latest your-app-name
Then ensure that you have selected the option where you will have pages inside your src directory.
Now you can refer to the below code to make your custom thumbnail.
Below is the code for generating thumbnail images from uploaded video
// src/pages/index.tsx
import Image from "next/image";
import { Inter } from "next/font/google";
import { useRef } from "react";
const inter = Inter({ subsets: ["latin"] });
const Home = (): JSX.Element => {
const previewVideo: any = useRef<any>();
const thumbnail = useRef<any>();
const doenloadBtn = useRef<any>();
const handleVideoUpload = (ev: any) => {
let file = ev.target.files[0];
if (!file) {
thumbnail.current.setAttribute("style", "display:none");
previewVideo.current.setAttribute("style", "display:none");
return;
}
//preview video
let url = URL.createObjectURL(file);
previewVideo.current.src = url;
previewVideo.current.removeAttribute("style");
let duration = 0;
previewVideo.current.onloadedmetadata = function () {
duration = previewVideo.current.duration;
const min = 1;
const max = duration;
/*
generating a random number within video
duration from which thumbnail will be generated.
It can be any number between 0 to video duration
in seconds
*/
previewVideo.current.currentTime =
Math.floor(Math.random() * (max - min + 1)) + min;
if (
!!previewVideo.current.videoHeight &&
!!previewVideo.current.videoWidth
) {
let counter = 0;
// This callback will be executed when ever we seek the preview
// video and it's current time changes
previewVideo.current.ontimeupdate = function () {
//generate thumbnail
let canvas: any = document.createElement("canvas");
canvas.width = previewVideo.current.videoWidth;
canvas.height = previewVideo.current.videoHeight;
canvas
.getContext("2d")
.drawImage(previewVideo.current, 0, 0, canvas.width, canvas.height);
let imageThree = canvas.toDataURL();
//This ensures that we generate thumbnail only for
//the first time the video is seeked i.e.
//current time set above and not when preview
//video starts playing
if (!!!counter) {
thumbnail.current.src = doenloadBtn.current.href = imageThree;
}
counter++;
thumbnail.current.removeAttribute("style");
};
}
};
};
return (
<main
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
minHeight: "100vh",
minWidth: "100vw",
background: "green",
}}
>
<form style={{ display: "flex", gap: "2rem", flexDirection: "column" }}>
<div
style={{ display: "flex", gap: "0.5rem", flexDirection: "column" }}
>
<label style={{ color: "#fff" }}>Upload video</label>
<input
onChange={handleVideoUpload}
accept=".mp4, .mov"
type="file"
name="video"
id=""
/>
</div>
<div style={{ display: "flex", gap: "2rem" }}>
<video
src=""
typeof="video/mp4"
style={{ display: "none" }}
controls
ref={previewVideo}
height={500}
width={500}
></video>
<a ref={doenloadBtn} href="" download>
<Image
height={500}
width={500}
src=""
alt="thumbnail"
ref={thumbnail}
style={{ display: "none" }}
/>
</a>
</div>
</form>
</main>
);
};
export default Home;
Hope this article helps and you can expand the code further or customise it according to your requirements.