The capture stream function we saw takes in one parameter, which is frame rate. But it is actually the maximum frame rate in which the video should be captured. Now, if the device on which the canvas, you know, is rendering the frames, if it is an underpowered device, the browser might decide to drop frames in order to improve the performance of rendering the frames on the canvas. And this is, you know, leads to lower reliability. You might have, you know, the same code working on two different devices, giving you two different outputs.
So there's no constant frame rate, the browser might at any time decide to drop frames to increase the performance. There is no option to change the video file format, it always produces an output of the WebM format, which is not really common with at least, you know, other re-editing softwares if you're trying to do something with them. There's low reliability as I mentioned, the code might give you two different outputs on two different devices because of the performance of both of them. And the output is also of decent quality, nothing too great, it might be bad because of the dropping frames. But yeah, it honestly depends on the performance of the device.
Now, it might seem like I'm trying to bash the media recording APIs here, but honestly they are not designed for such precise and high quality video exports. The media recording APIs are much more suited towards real-time applications where a trade-off of quality is acceptable as long as you're getting higher speeds. So if the capture stream cannot work, can we capture and encode individual frames of the canvas ourselves? So here's some pseudocode with this idea. So here what I do is in the loop, I seek the canvas to every frame, capture it as an image, and then process all the frames of the animation to a single video file. The loop starts by seeking the canvas to the frame. So here I've seeked it to the frame one. Then I capture the frame as an image using the toDataUrl function. And then I give it image-webp to capture it as a WebP image file. And then once the image is ready, I push it inside the images array. Then again, I seek to the next frame, I capture it as an image and store it in the images array. And once that's done for all the frames, I come outside the loop and with that images array I have, I can pass it to an encode function to encode it as a video file and download it on the user's device.
Now the real question here is, how do you encode an array of images to a video? Now this is not an easy problem to solve because till now, browsers haven't had a way natively to allow you to take an image array and convert it to a single video file. There are various libraries out there, and I will, at this point I would also like to give a mention to WAMI.js. WAMI is a real-time JavaScript WebM encoder. It appeared on Hacker News 11 years ago, which is kind of crazy. But what it does is it essentially takes snapshots of canvas as images and encodes them to a video file. And this is exactly what we're trying to do. Take a canvas, render the frame, capture it as image, encode them as a video file. This is how the function for encoding using WAMI looks like. So WAMI exposes a function called fromImageArray, takes in an array of images, which is the individual frames of your video.
Comments