How can I get the first frame of a video file in javascript as an image?
-
You mean client js or server-side js? If client side I don't think this is possible. – xandy Jul 21 '09 at 12:04
-
which video format? flv? avi? mov? – Shay Erlichmen Jul 21 '09 at 12:09
-
2are you using HTML5 video tags? – AutomatedTester Jul 21 '09 at 12:12
-
the format could be any of the above – Jul 21 '09 at 12:16
-
If server side, what server side framework/engine you using? – xandy Jul 21 '09 at 13:41
-
JavaScript doesn't have a native video processing feature. Browsers don't supply a video processing feature. You'll need to have a library that does this provided from somewhere else - if the JS runs server side then you would need the runtime you use to support it, if the JS runs client side then you would need something the JS can access there to do it (e.g. a Java applet). – Quentin Jul 21 '09 at 16:02
-
Javascript never runs on the server side! – Josh Stodola Jul 21 '09 at 16:51
-
4@Josh: except when it does! there are a lot of rows in that table over at http://en.wikipedia.org/wiki/Server-side_JavaScript – Jimmy Jul 21 '09 at 23:12
-
http://stackoverflow.com/questions/19175174/capture-frames-from-video-html5-and-javascript – john-jones Feb 17 '14 at 09:36
6 Answers
It can be done with HTML 5 video and canvas tags:
HTML:
<input type="file" id="file" name="file">
<video id="main-video" controls>
<source type="video/mp4">
</video>
<canvas id="video-canvas"></canvas>
Javascript:
var _CANVAS = document.querySelector("#video-canvas");
var _CTX = _CANVAS.getContext("2d");
var _VIDEO = document.querySelector("#main-video");
document.querySelector("#file").addEventListener('change', function() {
// Object Url as the video source
document.querySelector("#main-video source").setAttribute('src', URL.createObjectURL(document.querySelector("#file").files[0]));
// Load the video and show it
_VIDEO.load();
// Load metadata of the video to get video duration and dimensions
_VIDEO.addEventListener('loadedmetadata', function() {
// Set canvas dimensions same as video dimensions
_CANVAS.width = _VIDEO.videoWidth;
_CANVAS.height = _VIDEO.videoHeight;
});
_VIDEO.addEventListener('canplay', function() {
_CANVAS.style.display = 'inline';
_CTX.drawImage(_VIDEO, 0, 0, _VIDEO.videoWidth, _VIDEO.videoHeight);
});
});

- 1,484
- 2
- 20
- 44
-
4Did not work from me. I had to add 'video.currentTime = 0.001' as workaround, otherwise the image was blank. – Jan Moravec Feb 21 '21 at 22:06
-
3
Just add the video tag to the page with no controls and no auto-play.
<video width="96" height="54" class="clip-thumbnail"> ... </video>
Drawback is that users can play the video by right clicking the thumbnail and selecting "play" in the context-menu. To avoid that you'd need a little javascript listening for click events and cancelling them (removing context-menu from thumbnails).

- 584
- 6
- 14
-
To add to this you can use the `user-select: none` and/or `pointer-events: none` CSS properties instead of JS to remove context-menu and interactions (assuming you don't need them) – Javier Villanueva Jul 17 '23 at 17:23
As mentioned, Javascript is not able to do this.
If you want to create thumbnails for your videos you have to create the thumbnail server side and then simply serve up the image on the client as you would any other image.
My method of choice for accomplishing this is the ffmpeg decoder. It can handle a multitude of file formats and is able to do what you want. So if you have a video named hello.avi
, you might do:
ffmpeg -itsoffset -1 -i /path/to/hello.avi -vcodec mjpeg -vframes 1 -an -f rawvideo -s 200x150 /path/to/hello.jpg
You can run this command (fixing the paths and dimensions...) with whatever server-side language you are using and it would create a thumbnail of the video file.

- 480,997
- 81
- 517
- 436
Javascript is not capable of doing this.

- 81,538
- 47
- 180
- 227
-
It can be done on a client side with HTML 5 tags, see my answer below – Sergey Malyutin Apr 16 '19 at 09:15
It may be possible if the video is a file selected by the user into an <input type="file">
, you can get the base-64 video data using the FileReader API:
https://developer.mozilla.org/en-US/docs/DOM/FileReader
From there you're just left with the extremely intractable problem of decoding the video and somehow picking out and rendering a single frame, in javascript. Alternatively, you could just include the entire video as the "thumbnail preview" (I assume that's why you're doing this?), as demonstrated here:
http://hacks.mozilla.org/2009/12/file-drag-and-drop-in-firefox-3-6/
Not sure about the compatability of that last example though, or how well it work with larger video files (I hear you can easily bump up against URL length restrictions)

- 4,286
- 1
- 29
- 21
You can achieve this using canvas API.
Create the following function:
This will generate a png file for the specified frame.
export const videoToImage = (
videoFile: File,
options: {
frameTimeInSeconds?: number
filename?: string
extension?: string
} = {
frameTimeInSeconds: 0.5,
extension: "png"
}
): Promise<File> => {
return new Promise<File>((resolve) => {
const canvas = document.createElement('canvas')
const video = document.createElement('video')
const source = document.createElement('source')
const context = canvas.getContext('2d')
const urlRef = URL.createObjectURL(videoFile)
video.style.display = 'none'
canvas.style.display = 'none'
source.setAttribute('src', urlRef)
video.setAttribute('crossorigin', 'anonymous')
video.setAttribute('preload', 'metadata')
video.appendChild(source)
document.body.appendChild(canvas)
document.body.appendChild(video)
if (!context) {
return
}
video.currentTime = options.frameTimeInSeconds
video.load()
video.addEventListener('loadedmetadata', function () {
canvas.width = video.videoWidth
canvas.height = video.videoHeight
})
video.addEventListener('loadeddata', function () {
setTimeout(() => {
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight)
canvas.toBlob((blob) => {
if (!blob) return
resolve(
new File([blob], (options.filename || videoFile.name) + "_preview."+options.extension, {
type: 'image/' + options.extension
})
)
URL.revokeObjectURL(urlRef)
video.remove()
canvas.remove()
}, 'image/' + options.extension)
}, 2000)
})
})
}
Usage:
videoToImage(videoFile).then((image: File) => {
console.log(image)
})
Description: This function receives a video file and creates a canvas loading the video source to take a snapshot of its contents and generate a new png file.
OBS: Delay is required to make this work on mobile devices.

- 1,256
- 14
- 15