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

Support for saving animations #116

Open
Kevinpgalligan opened this issue Nov 9, 2023 · 5 comments
Open

Support for saving animations #116

Kevinpgalligan opened this issue Nov 9, 2023 · 5 comments

Comments

@Kevinpgalligan
Copy link
Contributor

Kevinpgalligan commented Nov 9, 2023

It's currently a hassle to capture a video of an entire sketch. Once the sketch window shows up, it is often too late to start recording. The user can build a delay into their sketch to give themselves more time, or they can save a PNG in each frame and then stitch those together using external software like ffmpeg. However, I think it would be more user-friendly to have built-in support for saving animations.

I initially considered the skippy package, since it's native CL, but I'm not sure that GIF is the best output format given that (from my understanding) it doesn't support transparency and requires that colours be mapped to a limited palette. So, it might be better to just require a dependency on some video-encoding library that there are CL bindings for.

(Yes, there are probably more convenient workarounds for this using external software, but that all falls under the category of "extra hassle for the user").

@vydd
Copy link
Owner

vydd commented Nov 9, 2023

I wouldn't say it's a high priority, but if there's an easy way to do it - go for it! If there's a huge amount of dependencies, maybe it can live in another system, e.g. sketch-extras.

@Kevinpgalligan
Copy link
Contributor Author

I asked around on the #commonlisp IRC channel, Josh_2 generously shared their code for transcoding between video formats using a uiop:run-program call to ffmpeg:

https://plaster.tymoon.eu/view/4042#4042

I think I'll try something similar.

@Kevinpgalligan
Copy link
Contributor Author

I've implemented a basic version of this here: Kevinpgalligan@b6f8297

Example usage:

(defsketch bw ((i 0))
  (if (< 30 (mod i 60))
      (background +white+)
      (background +black+))
  (incf i))

(record-sketch 'bw "/tmp/foo.mp4")

When you exit the sketch with ESC (or however), you should get a video at /tmp/foo.mp4 that alternates between an all-white and all-black screen.

TODO:

  • More testing (I've only tested it with that simple sketch).
  • Allow tweaking the ffmpeg parameters.
  • Error checking (ffmpeg isn't installed, or fails to start properly. Maybe try to ensure that the static vector gets cleaned up, even if SDL2 crashes, if that's possible).
  • Make use of the :frames and :until keyword arguments, which let the user say "record for 10 seconds" or "record for 1000 frames".

@Kevinpgalligan
Copy link
Contributor Author

Kevinpgalligan commented Nov 9, 2024

Managed to record one of my sketches, so I'm fairly confident it's working as expected:

growth.mp4

It should probably save the frame before the first draw call when copy-pixels is set, e.g. in this sketch the canvas starts out as all black.

@Kevinpgalligan
Copy link
Contributor Author

Kevinpgalligan commented Nov 9, 2024

Most of that is now done: Kevinpgalligan@4af5468

However, I discovered that the video is reflected around the horizontal axis for some reason. ffmpeg must be expecting the data to start from the bottom-left corner when it actually starts from the top-left corner, or vice versa. I'll see if there's an ffmpeg flag to flip the order.

(Edit: fixed).

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

No branches or pull requests

2 participants