For some time I have been having trouble with producing short movies/animations/gifs which are of sufficiently high resolution. I'm going to use R to generate some frames as a random example, but if there is somewhere else I should be creating frames from to give better results I would be interested in that too.
Creating frames
The kinds of animations I'm interested involve some cloud of 'particles' moving about the page. There are usually a large number of particles and I would like their motion be as smooth as possible. As a random example, consider the R code (using base graphics and not ggplot2
as it is far quicker for saving a large number of frames)
N <- 500
nFrames <- 250
points <- pracma::randp(n=N, r=1)
rot <- function(p, a) { return(cbind(p[,1]*cos(a) - p[,2]*sin(a), p[,1]*sin(a) + p[,2]*cos(a))) }
cols <- colorRampPalette(c("red", "green", "blue"))(nFrames)
ang <- seq(0, pi, length=N)
# Save frames
png(filename="%d.png")
par(mar=c(0,0,0,0))
for (i in seq(1,N,length=nFrames))
plot(sqrt(i)*rot(points, ang[i]), xlim=sqrt(N)*c(-1,1), ylim=sqrt(N)*c(-1,1), cex=0.5, pch=19, col=cols[i], asp=1, xaxs="i")
dev.off()
Frames to animation
There are a number of tools available to chain each frame together into an animation (in R there are also things like gganimate
which I have tried but did not find convenient or better than the following). I also don't have any requirements for the resulting file size or time taken to get everything looking as crisp as possible.
convert
For short gif style animations a common solution is to do something like convert -delay 1 -loop 0 *.png g.gif
which gives
gifski
Running gifski -o g.gif *.png
produces
There is an annoying amount of 'jitter' happening in the transition between frames in both of the above (though less noticeable with gifski
).
ffmpeg
Being gifs, the above will be have limited options for tweaking so I suspect part of the solution lies in using ffmpeg
. All I would like to know is how to make the animation appear totally smooth without any kind of noticeable blurriness. Here the resulting movies tend to be quite smooth, but resolution is lacking.. e.g. after setting height=1080
and width=1080
in png()
of the above code we can run
fmpeg -i %d.png -s 1080x1080 -c:v libx264 -vf fps=250 -pix_fmt yuv444p out.mp4
If the particles move on a time/space scale smaller than is visible to the naked eye, and we set the frames per second to be the total number of frames, the transition between frames should be seamless, right? At around the 2 second mark in out.mp4
you will see some kind of frame drop and similarly right at the beginning. Why does this happen?
Questions
- Is there a standard documented approach to generating high quality animations/movies involving large numbers of 'point-like' particles? Do we need more an more frames?
- How to improve resolution of movies using
ffmpeg
? Should I change from .png format to something vectorised (if so, how)?
Running Fedora v31.