About a month ago I got the request to create a video from one of the WebGL demos on this site (the rotating earth cube, showing population density). So, of course, I said yes, but creating high quality output of this animation wasn’t as easy as I thought. I looked at a couple of screen recording tools, but none were available for Mac that were free, offered a good resolution and high enough frame rate. To be honest, I didn’t really look that long since I thought it a good opportunity to see how I could get the content of just the single canvas/webgl element and export it to a movie.
So basically, after some looking around, I came across this link where someone used websockets to export the content of the canvas and save these captures individually. Finally at the server side we can use ffmpeg to convert these captures to a movie. This looked like an interesting approach, so I did pretty much the same thing. I, however, used a simple vert.x backend for the websocket server.
This piece of code uses the toDataURL() function to get the data from the canvas element, next it converts it to a bytearray so we can easily send it as a binary websockets message. Making it binary is a bit of overkill for this example I guess, but this was the approach I had the best result with. And this is it for the websockets client part. One last important thing to note here, is that you should make sure you cal the “sendToServer” after the canvas is rendered. This might seem obvious, but costed me a lot of time bug hunting. I assumed that it wouldn’t matter if I added it before or after, since there is always something rendered on the canvas, and thus available to be sent to the server. Well… this isn’t the case. The canvas is apparently cleared at the beginning of the render loop, which caused a lot of black screens to be sent to the server.