Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export animated svg as .mov or .mp4 #228

Open
michaelrommel opened this issue Aug 23, 2020 · 6 comments
Open

Export animated svg as .mov or .mp4 #228

michaelrommel opened this issue Aug 23, 2020 · 6 comments

Comments

@michaelrommel
Copy link

Dear maxwellito,

thank you very much for the library and the vivus instant website - it is a joy to use!

I wondered, if there are any recommendations or best practises, when one wants to export the animated svg into a video with a defined resolution (FullHD or 4K).

At the moment I have embedded the resulting svg in a website and perform a screen recording while the browser plays the animation. I encountered two difficulties:

  1. Timing

When the animation is being played back too quickly, the screen recorder misses frames and the resulting video is yanky. I overcame this by having the exported animation from vivus instant set to a 4x longer time, then I post process the recorded animation and speed it up 4x. This produced good results. Also, if I record on a 4KTV with a 60HZ refresh rate, the grabbed video is more yanky, than when I record it on a 120 Hz refresh rate monitor. After the post processing, though, both are practically the same.

  1. Resolution

Because of the screen grabbing, I actually can only record in resolutions below the monitor's resolution and lose a bit of detail.

Therefore I was looking for a way to export the animated frames into a movie (or a series of image, that I could then import into Final Cut). Does anyone know about any such solution?

Thank you in advance. If this is not the right way to ask for help, please feel free to tell me, I will then close this issue.

All the best,

Michael.

@maxwellito
Copy link
Owner

Hello Michael,

First, thanks for your kind words. Its always nice to hear from users :)

Your issue is a very interesting one. I must admit, I had to think about a solution for a similar problem but never had the chance to implement it.

Let's start by the library constraints. Vivus uses requestAnimationFrame to time intervals between frames. Depending on your machine/SVG complexity the frame rate might vary. In this case it will be difficult to increase the frame rate as you need.

My guess, to make it possible, would be the following stack:

  • Your webpage containing the animation and the styling required
  • A Puppeteer script to open the page at the resolution of your choice, and render each frame and export it. (This is doable by setting the progress of the animation with .setFrameProgress(progress))
  • FFMPEG script to combine all the pictures into one video. Or import them into Final Cut if you prefer.

I dunno if it's what you had in mind. I'm happy to give more details and help you start the project.

I hope this helps :)

@michaelrommel
Copy link
Author

Hi,

thank you for your speedy reply - I also thought about puppeteer, as I am using this already for GUI tests. But I looked into animTimingFunction instead of the setFrameProgress function - so I will give that a try. If I read this correctly, then let's say given I want a roughly 2 sec intro of a video in 60p I would run the argument to that function from 0 to 1 in 0.008 increments which results in 125 images. I will give that a try next weekend and let you know how it went. Right now I am busy with work...

Thanks for the helpful hint!

Michael.

@maxwellito
Copy link
Owner

maxwellito commented Aug 26, 2020 via email

@netsi1964
Copy link

Perhaps if you added an event to Vivus, so that for every frame you triggered an event frame which people then could hook into? Using something like Puppeteer then, you might generate a screenshoot of that current frame.

@maxwellito
Copy link
Owner

It's something doable with the base API

// Init the Vivus instance
const duration = 200;
const myVivus = new Vivus('svgId', {duration, start: 'manual'});
let currentFrame = 0;

// Function to move to the next frame
// Will return 'true' once the last frame is reached
function nextFrame () {
  myVivus.setFrameProgress((currentFrame++)/duration);
  return currentFrame === duration;
}

@jdexyz
Copy link

jdexyz commented Dec 4, 2020

Hi,
I ended up making a super quick and dirty Electron app to solve this very issue.
https://github.com/jeremypatrickdahan/vivus-electron

It is essentially a giant security hole, so never use this in production or with untrusted svg files...
It is quite difficult to preserve transparency with video. I ended up using a quicktime codec (qtrle), though webm also works.

Ho, and resolution is set at 2K, although it is quite easy to change. It is easy to modify to only get the PNG sequence to import it in a video editor.

EDIT : I had some more time to play with this. This quick app is actually for a relative, who uses an iPad for video editing. So I needed to export everything as HEVC with an alpha channel, which is only possible on macOS Catalina for now. So FFMPEG is tuned for Apple ProRes4444 (and no longer qtrle) and then avconvert (the macOS version of avconv) converts to HEVC + alpha. It works well and the resulting files are very small, but everything is currently very slow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants