Converting html to mp4
Such an obvious problem, convert a piece of html/js/css, often with animations, to a video (mp4 or similar). We were just put before this problem for the TUG 2020 online conference. Searching the internet it turned up mostly web services, some of them even with lots of money to pay. At the end (below I will give a short history) it turned out to be rather simple.
The key is to use timesnap, a tool to take screenshots from web pages. It is actively maintained, and internally uses puppeteer, which in turn uses Google Chrome browser headless. This also means that rendering quality is very high.
So having an html file available, with all the necessary assets, either online or local, one simply creates enough single screenshots per second so that they can be assembled later on into a video with ffmpeg.
In our case, we wanted our leaders to last 10secs before the actual presentation video starts. I decided to render at 30fps, which left me with the simple invocation:
timesnap Leader.html --viewport=1920,1080 --fps=30 --duration=10 --output-pattern="leader-%03d.png"
followed by conversion of the various png images to an mp4:
ffmpeg -r 30 -f image2 -s 1920x1080 -i leader-%03d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p leader.mp4
-r is the fps, so needs to agree with the
--fps above. Also the
-s values should better agree.
-crf is the video quality, and
-pix_fmt the pixel format.
With that very simple and quick invocation a nice leader video was ready!
It was actually more complicated than normal. For similar problems, it usually takes me about 5min of googling and a bit of scripting, but this time, it was actually a long way. Simply searching for “convert html to mp4” doesn’t give a lot but web services, often paid for. At some point I came up with the idea to use Electron and led to Electron Recorder, which looked promising, but didn’t work.
A bit more searching led me to PhantomJS, which is not developed anymore, but there was some explanation how to dump frames using phantomjs and merge them using ffmpeg, very similar to the above. Unfortunately, the rendering of the html page by phantomjs was broken, and thus not usable.
Thus I ventured off into searching for alternatives of PhantomJS, which brought me to puppeteer, and from there it wasn’t too long a way that pointed me at timesnap.
Till now it is surprising to me that such a basic task is neither well documented, so hopefully this page helps some users.