uxebu / bonsai

BonsaiJS is a graphics library and renderer
http://bonsaijs.org
Other
1.96k stars 189 forks source link

Save SVG to Image on tick #222

Open ajarti opened 10 years ago

ajarti commented 10 years ago

Hi guys, I am looking to save the animations out to frames (images) and then stitch with ffmpeg to video. The objective is that some low end devices like the Raspberry Pi have shocking browser rendering rates, yet have dedicated hardware video decoding.

Is there a way to do this with the clock tick emitter on animations?

Thanks in advance.

basecode commented 10 years ago

First of all: Awesome idea! There is nothing build-in and I'm not sure it makes sense to implement it. The Runner does not have access to real pixels. Neither per Frame nor in general. The renderer on the other side has access. Maybe we could advice the Renderer to take a snapshot of the Stage per "tick" and put the data somewhere. I would suggest extending the existing SVG-Renderer and experimenting with writing the buffer to a Canvas2d context per Frame within render method and fetch the image from there.

if you need further infos please don't hesitate to ask. This would be a neat pre-build feature or Orbit tool btw.

nonken commented 10 years ago

Cool idea +1

ajarti commented 10 years ago

Thanks for the reply Basecode, glad you like the idea :)

I would suggest maybe using base64 encoded images in an array on the browser and then uploading/pushing to the server for ffmpeg stitching ending in a download of the clip.

The only issues is how long the animation is and how many frames/fps are needed. One might have to slow down the render to allow for the images to dump, upload and clear so as to not exhaust available memory. Especially given you can't predict the upload speed of the client.

I unfortunately have no idea how to do that and I'm not a good enough developer either .. lol

Any takers? :)

iamdustan commented 10 years ago

Create a gif in the browser! http://jnordberg.github.io/gif.js/

See it in action on my favorite website! http://hdragomir.github.io/facetogif/

kvilon commented 10 years ago

Hi!

I've done several experiments to convert bonsai-animation to gif. Here is a demo: http://estas.github.io/bonsai-gif/

  1. First of all, I redefined bonsai.Renderer.prototype.render function to be able to save SVG frames to an array.
  2. Saved SVG images are converted to base64 with window.btoa() and then drawn on a 2d context. btoa() works pretty well in modern browsers and IE >= 10.
  3. Finally, the array of base64 images is put to GIF.js. A good feature of GIF.js is that it encodes the frames with web workers. However, there are also few bugs: incorrect background for transparent parts of images, it's impossible to turn off console logs, etc. In general, testing is needed.

I've tested it in Chrome 35 (win7) and Firefox 30 (win7). Chrome is ok, but recording several hundreds of frames in Firefox appeared to be a little bit troublesome.

After all, I'm sure that with certain refinements it's possible to bring the gif feature to a fully working state and add it to the Orbit tool. I can help it, in case you are interested!

1eae11d8-b0f4-46d2-8f87-d5ec8df103ba

basecode commented 10 years ago

You did it! :)

For what I see overwriting bonsai.Renderer.prototype.render is the only way to make that work. +1 I think adding the converter to Orbit would only interrupt your current workflow. That's way I'd prefer having your converter on http://estas.github.io/bonsai-gif/. Feel free to enhance the design of your page with any assets/styles you can find on http://orbit.bonsaijs.org/ to make it more look like Orbit. For sure it would be nice to be able to feed the converter with existing Bonsai code. If we see that the converter works with most of the Bonsai movies we could integrate it or redirect to your converter.

Great work!

kvilon commented 10 years ago

Thank you very much for your feedback! You can check out a new demo at the same page (http://estas.github.io/bonsai-gif/). I followed your advice and now it looks better and more Orbit-like. Please, pay attention to a small button "Rec" in the bottom-right corner :)

I've changed the functionality as well. The recorder now has two new settings: a ratio of the Bonsai frame rate to the desired gif frame rate (the default 60 fps is too much for a gif, and therefore there should be a possibility to set up the ratio; in the demo the ratio is 3) and a "recLength", which limits a number of frames to record and, hence, prevents a user from waiting too long. Furthermore, one can stop gif.js encoding by clicking the same button while processing.

As a result, most of Bonsai animations are converted to gif with a fairly high quality.

However, there are some disadvantages:

  1. I have to remove Xlink attributes from text elements to be able to convert animations containing them.
  2. Not all colors are converted ideally. Because of that, gradients, shadows and blurring look not so good. Probably, it's a limitation of theGIF format itself. Also, opacity works, although you can notice it only when objects overlap.
  3. In the gif.js library there are "background" (background color of regions where source image is transparent) and "transparent" (transparent hex color) properties, and, unfortunately, "background" is set to "black" by default and there is no way to change it without fixing the source of the library and rebuilding it. I set "transparent" to "black" in order for pictures to have transparent background, but this causes all other black elements (text, borders, etc.) to became transparent.
  4. Converting SVGs with external pictures do not work.
  5. Gif.js clutters the console with lots of messages, which one cannot turn off.