I made a web app that helps you extract screenshots from a video file. You technically don't "upload" it but you select a video file from your computer into the web app, and the screenshots are generated more or less instantly.
Canvas Web API
Why did I make this app? Because I wanted to experiment with the Canvas (Web) API and how it can be combined with a video
element. I originally typed into some AI prompt and got most of the code from that, but I felt like I didn't understand it. And to be able to quickly iterate and play with it, I ended up making a simple web app so that I can tune it.
How it works
The gist of the code is this:
export function createVideoThumbnail(
videoFile: File,
options: Options,
): Promise<string> {
const { quality = 1.0, captureTime = 0.1, format = "image/jpeg" } = options
return new Promise((resolve, reject) => {
const video = document.createElement("video")
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
if (!ctx) {
reject(new Error("Failed to get canvas context"))
return
}
video.preload = "metadata"
video.muted = true
video.playsInline = true
const videoUrl = URL.createObjectURL(videoFile)
video.src = videoUrl
video.onloadedmetadata = () => {
const width = video.videoWidth
const height = video.videoHeight
canvas.width = width
canvas.height = height
video.currentTime = captureTime
}
video.onseeked = () => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
const dataURI = canvas.toDataURL(format, quality)
URL.revokeObjectURL(videoUrl)
resolve(dataURI)
}
video.onerror = () => {
URL.revokeObjectURL(videoUrl)
reject(new Error("Error loading video file"))
}
video.load()
})
}
See src/create-video-thumbnail.ts
on GitHub.
The project
The code for it is here: https://github.com/peterbe/video-to-screenshots
The web app is hosted on Firebase Hosting. The foundation of the code is React with react-router
, and uses pico css. I use Bun and Vite to run and build the app.
Conclusion?
It works and it's basic. You can download the JPEGs. It's not very pretty. It's a weekend project and it accomplishes something.
But it doesn't work in Safari. Anybody got any ideas?
Perhaps it would be cool to allow the user to see many many more thumbnails and allow them to specify more exactly which capture times to make screenshots out of. What do you think?