Four years ago I created a HD fractal movie because I wanted to see how quickly Fractal eXtreme could calculate the same movie that Orson Wang had posted to youtube. My version of his movie was antialiased and 720p and seemed pretty impressive at the time. I discussed it here.
I recently got a 4K TV and I realized that my “HD” video looked blurry on it. So I decided to make a new version, at 4K resolution instead of just 720p, with improved colors and other tweaks.
Standing a few feet in front of the 4K TV while this new movie plays makes me happy. It is the zoom-movie perfection that I have imagined since I released my first fractal program in 1986. I think it’s beautiful, and I also think that it is profound that all of this complexity comes from a formula as simple as Z = Z * Z + C.
Creating a 4K video was challenging:
- My laptop doesn’t support 4K so I had to update the zoom movie player to allow saving frames larger than the display.
- The AVI format I’d previously used to export videos doesn’t handle 4K and the files would have been too large anyway so I had to update the zoom movie player to allow saving frames as PNG files – this was long overdue.
- None of my video editing programs (Camtasia, Windows Live Movie Maker, Adobe Premiere Elements) supports 4K so I had to use ffmpeg to stitch 18,117 frames together, which also meant I had to code up my own scrolling credits.
- Rendering the movie was going to take a month on my laptop so I switched to a 20-core/40-thread machine, but this revealed long-standing performance bugs. There were a couple of image finalization tasks which ended up being run once per thread, and on high-resolution images this could cause a 5-10 second hang at the end of each image!
- I couldn’t view the resultant movie on my laptop.
After tweaking the palette and other settings I loaded the same image used for my 720p movie (and the same location used in the 480p Orson Wang fractal movie that got me started) and set the resolution to 2,488 by 1,400, with 3 by 3 antialiasing. This means that each image requires calculating more than 31 million pixels in order to produce 3.5 million antialiased pixels. I then told Fractal eXtreme to render a zoom movie, which it does by rendering 917 separate images, starting from zoomed all the way out and doubling the magnification for each subsequent image until the final destination is reached. This took 5 days, 17 hours, and 8 minutes. That may seem like a long time but on the last image it was doing all the math to 960-bit (288-decimal-digit) precision and doing billions of iterations of the Mandelbrot formula – up to ten million per pixel.
2,488 by 1,400 is not 4K resolution, but when movie frames are generated the multiple images are combined so that the center of the image is always at full 4K resolution. It does this by using the next frame to fill in the middle – sort of like a really long mip-map chain. The edges may be slightly blurry but it turns out that “slightly blurry” at 4K resolution is still pretty damned sharp. Ideally the source images would have been higher resolution, but that could have taken days longer and would have made very little difference.
I then loaded the zoom movie into the Fractal eXtreme Movie Player. It loaded all 917 frames which consumed 9.4 GB of RAM. My laptop doesn’t actually have that much RAM, but I’ve got a fast SSD and the memory access patterns are friendly. But, still. Don’t try this on an underpowered computer.
I then used the Save as AVI or PNG menu option (PNG saving is new) to export the movie. Changing the movie name to have a .png extension is all that is needed to enable saving PNG frames, which are much more compact and less finicky than AVI files. Setting the output resolution to 3840 by 2160 is also a new option, added for this project. 60 frames/second is recommended. Finally, in order to avoid having the movie zooming at the same speed through the boring parts as well as the detailed areas I used a custom zoom file, as described in this post. The movie player automatically does smooth transitions between zoom speeds for a very pleasing effect.
The 3840×2160 png files vary from just 27,040 bytes to a large 14,592,685 bytes, averaging 3,3650,80 bytes (58,515,384,188 bytes in 17,388 files). Exporting all 17,388 frames took about six and a half hours. Take a nap.
Assembly a movie file
Since none of my movie editors could handle 4K resolution I had to learn to use ffmpeg. I have mixed feelings about this. On the one hand, it worked. On the other hand, it was incredibly finicky and I still don’t understand some of the weird failures.
The simplest way to use ffmpeg – and the only way that I got to work reliably – was this syntax, from my build batch file. I don’t know if the duplicate “-r60” directives are necessary, but don’t mess with something that works. This basically says to get all files that match the pattern “Frames%06d.png”, glom them together at 60 fps, add the audio file specified in the %audio% environment variable, and h264 compress the whole lot.
ffmpeg -r 60 -i Frames%06d.png -i %audio% -crf 13 -vcodec libx264 -pix_fmt yuv420p -r 60 %outputName%
-crf 13 requests relatively high quality – high enough that I stopped noticing any difference. The default is 23, with zero being lossless. Using “-crf 0” would completely avoid recompression artifacts, but it would make the video files ten times larger for no visible benefit – youtube is going to compress it eventually anyway.
If I cared about compressing the movie file as much as possible then I’d use a preset that spent more time in order to compress more aggressively, but maximum compression was not actually important. I was just going to upload the file to youtube and then delete it.
I had a series of 300 PNG files for the opening credits, and 429 PNG files for the scrolling credits, so I had to write a python script that would create hard links to these three separate sets of files so that they would appear like a single set. I tried using ffmpeg’s “-f concat” syntax instead but it was finicky and I eventually decided I didn’t trust it or need it. A directory of links worked better. To get the audio to not start until the title was finished I edited the sound track to insert five seconds of silence. Crude, but effective. These are the things you do when your video editors can’t handle the task.
Converting to h264 took an hour and forty minutes.
The only way to test the final video was to upload it to youtube, and that took about 35 minutes each time, to upload 1.5 GB of h264 video. In order to avoid doing that too often I tweaked my scripts to do subsets of the full video. I also used “-vf scale=1280:720” to generate lower resolution videos and I used the mpeg codec in order to get a movie that I could play on my computer (although, with significant visual artifacts for some reason).
And that’s it – pretty straightforward once I had the bugs fixed, new features added, and ffmpeg figured out. It will be much easier the second time.
Fractal eXtreme fixes and features
Fractal eXtreme was originally written in 1996. My development machine only had one CPU, but I had access to a dual-socket Pentium-Pro which gave me a chance to do multi-core testing. Thus, Fractal eXtreme did multi-threaded rendering from the very beginning.
But, the multi-threaded code was not great. It’s amazing that it’s continued to work for this long, but I guess I shouldn’t be surprised that I found some problems with how it scaled. These bugs required both large images and many cores to become visible. The recent fixes to Fractal eXtreme include:
- Fixed bugs that caused two image finalization steps to run once on each worker thread, causing multi-second hangs on many-core machines on high-res images
- Fixed limitations that prevented guessing from working on the last four chores
Movie player fixes and features
I also found a few bugs in the zoom movie player, but mostly it needed new features, to allow saving PNG files at arbitrary resolutions:
- Added support for saving movies as .bmp or .png instead of just as AVI
- Fix BMP saving to specify the file size in the header so that ffmpeg can handle it
- Fixed movie player bug that would sometimes cause jumps when crossing zoom-level boundaries
- Allow saving zoom movies to any size instead of always to the output window size, to allow rendering 4K movies on any machine
- Add optional text display of the zoom level to movie playback
That’s it. Give Fractal eXtreme a try, make some high-res movies, or just enjoy the many high-res fractal movies that other have created, using the simplest fractal formula. Here’s my contribution. For best results put this on a large 4K TV screen and stand close. Searching for OneWheelGuy1 is one way to locate it.
Hacker News discussion of this post can be found here.