I am testing HTML5’s video API. The plan is to have a video play with an effect, like making it black and white. I have and working together using a buffer. I take the current video frame and copy to the scratch buffer where I can process it. The problem is the rate at which it runs.
The Video API of HTML5 has the ‘timeupdate’ event. I tried using this to have the handler process frames, once for every frame, but it runs at a slower rate than the video.
Any ideas to speed up processing frames?
You can get much more frequent redraws by using requestAnimationFrame to determine when to update your canvas, rather than relying on
timeupdate, which only updates every 200-250ms. It’s definitely not enough for frame-accurate animation.requestAnimationFramewill update at most every 16ms (approx 60fps), but the browser will throttle it as necessary and sync with video buffer draw calls. It’s pretty much exactly what you want for this sort of thing.Even with higher frame rates, processing video frames with a 2D canvas is going to be pretty slow. For one thing, you’re processing every pixel sequentially in the CPU, running Javascript. The other problem is that you’re copying around a lot of memory. There’s no way to directly access pixels in a video element. Instead, you have to copy the whole frame into a canvas first. Then, you have to call
getImageData, which not only copies the whole frame a second time, but it also has to allocate the whole block of memory again, since it creates a newImageDataevery time. Would be nice if you could copy into an existing buffer, but you can’t.It turns out you can do extremely fast image processing with WebGL. I’ve written a library called Seriously.js for exactly this purpose. Check out the wiki for a FAQ and tutorial. There’s a Hue/Saturation plugin you can use – just drop the saturation to -1 to get your video to grayscale.
The code will look something like this:
The big down side of using WebGL is that not every browser or computer will support it – Internet Explorer is out, as is any machine with old or weird video drivers. Most mobile browsers don’t support it. You can get good stats on it here and here. But you can get very high frame rates on pretty large videos, even with much more complex effects.
(There is also a small issue with a browser bug that, oddly enough, shows up in both Chrome and Firefox. Your canvas will often be one frame behind the video, which is only an issue if the video is paused, and is most egregious if you’re skipping around. The only workaround seems to be to keep forcing updates, even if your video is paused, which is less efficient. Please feel free to vote those tickets up so they get some attention.)