Capturing an image from an HTML5 Canvas or Video Element
Ever want to save your HTML5 canvas element as an image? You totally can! I’ve done this a few times to solve a variety of different issues. With this trick you can capture a screenshot from a video, save a rendered graphic, pretty much anything within the canvas element.
Step 1: Make a Reference To your Canvas Element
There are two approaches to this. First, you may have a canvas element that actually appears on the screen. It will live within your HTML and will display on the screen. The second approach is to have the canvas element represented simply as a javascript object. I’ve used this approach to capture screen shots of HTML5 video elements.
If your canvas is within HTML, make a reference to it in your Javascript like this:
let canvas = document.getElementById('screenshot-canvas');
You can obviously use whatever reference way you choose to select your canvas from the screen.
You can also just have a canvas object behind the screen that can be used to capture what’s within. I just set it up like this:
let canvas = document.createElement('canvas');
Step 2: Capturing your Canvas Element as an Image
Here’s where the magic takes place. I create a method that captures the element like this:
let image = canvas.toDataURL('image/jpeg');
With canvas
being the variable of your HTML5 canvas element we set up in step 1. That’s all there is to it! You now have a capture of whatever is in the canvas as an image! You can set the image
variable to the src
of any image element and you will be good to go.
One thing to note. The size of your image will be the size of your canvas. This is much easier to see if the canvas is on your screen. However, if you are using a Javascript object, you need to set the width
and height
of the element like so:
let canvas = document.createElement('canvas');
canvas.width = 1920;
canvas.height = 1080;
Taking a Screenshot of an HTML5 Video Element
One of the coolest features of this script is you can take a screen shot of an HTML5 video element using this as well. You just have to pipe the video to the canvas element. Just a heads up, this will work better if the canvas you are referencing is a javascript object, otherwise you will have 2 videos on your screen.
To do this, set up a reference to your HTML5 Video Element. I’m going to assume this element lives on your page. You can however, do the same object instantiation of the video element and hide both the canvas and video element and just output a screen shot. If you are interested in those examples, reach out on the community forum.
Let’s first set up the reference to our HTML5 video element:
let video = document.getElementById('my-video');
Once again, you can use whatever method you want to reference your video. We just need a reference to the element.
Now that we have our video, let’s tie everything together. For best results, I’d recommend keeping the aspect ratio of your canvas to the size of your video. It doesn’t have to be the full size if you want smaller, scaled images, but you also don’t want any funky resizing.
let canvas = document.createElement('canvas');
let video = document.getElementById('my-video');
canvas.width = 1920;
canvas.height = 1080;
let ctx = canvas.getContext('2d');
ctx.drawImage( video, 0, 0, canvas.width, canvas.height );
let image = canvas.toDataURL('image/jpeg');
That’s all there is to it! The meat of the script is to create a “2D” context and draw an image to that context of the video. This will take whatever frame is currently being displayed on the video and capturing it as an image.
Capturing an HTML5 Video Frame at a Timestamp
If you want to capture a frame at a certain timestamp in your video, there’s one little gotcha. You have to use the seeked
callback to make sure your video has finished seeking before you capture the frame.
All you have to do is modify your code to look like this:
let canvas = document.createElement('canvas');
let video = document.getElementById('my-video');
let image = '';
video.addEventListener('seeked', function(){
canvas.width = 1920;
canvas.height = 1080;
let ctx = canvas.getContext('2d');
ctx.drawImage( video, 0, 0, canvas.width, canvas.height );
image = canvas.toDataURL('image/jpeg');
});
video.currentTime = TIME_IN_SECONDS;
Now whatever you set for the current time on the video in seconds, the video will seek to that location and take a snap shot.
Hopefully this helps! It’s kind of a neat feature of the HTML5 canvas element that you can save it as an image. If you have any questions, definitely feel free to ask on the community forum, I’d be happy to help!