Recording Frame-Perfect, High-Resolution Screencasts on Linux in the Year 2014
Posted on 2014-06-30 20:35 by Timo Bingmann at Permlink with 2 Comments. Tags: #vncrec
Last week I produced a recording of a talk about "STXXL 1.4.0 and Beyond". I thought it would be trivial in the year 2014 to create a frame-perfect high-resolution recording of a PDF presentation slideshow with moving mouse cursor on Linux. I was so wrong.
In the end, I created a patched version of vncrec: now called "vncrec-rgb 0.4", and the tutorial on the vncrec-rgb
webpage. But now, why do screen recording with vncrec
?
ffmpeg -f x11grab
works, but full-resolution encoding is too slow!
Searching the web revealed that ffmpeg now has support for capturing from X11, and there are many screencasting tools now available on Linux. Most of these are mainly frontends to xvidcap
or ffmpeg
, and call some variation of the ffmpeg
command lines below:
# Capture screen :0 in full HD resoltion, compress with HuffYUV codec and save to out.avi
$ ffmpeg -f x11grab -y -r 25 -s 1920x1080 -i :0.0 -vcodec huffyuv out.avi
# Capture screen :0 with audio, otherwise the same as above.
$ ffmpeg -f alsa -ac 2 -i hw:0,0 -f x11grab -y -r 25 -s 1920x1080 -i :0.0 -vcodec huffyuv out.avi
# DO NOT USE THESE LINES, READ BELOW!
Even in the year 2014 it was not possible to capture the screen in full HD resolution 1920x1080 losslessly in real time. None of the low-overhead lossless codecs huffyuv
, ffv1
, or lossless x264
were fast enough for a modern desktop to capture and transcode the full HD resolution on-the-fly. Even worse, the output files of the ffmpeg
lines above had silent frame drops which yielded in audio desync. This is probably the reason why the front-end Linux screencast tools usually down-scale the resolution while recording! I find this unacceptable.
Problems with YUV colorspace and vncrec-twibright
Well, after much ado, I reverted back to the method I used a long time ago, in 2009, to record a screencast: vncrec
. See the corresponding blog post "Experiences Producing a Screencast on Linux for CryptoTE" for some more discussion on why vncrec
is a very good solution for producing frame-perfect screencasts.
However, I noticed one problem with the vncrec-twibright
edition: bleeding edges and some "washed-out" colors. These artefacts are due to vncrec-twibright
's conversion of the frames into the YUV 4:2:0 colorspace, which is nice for videos but of course does not match the RGB colorspace of a screencast.
This is however not a limitation of the vnc recording, the vncrec -movie
option could just as well be outputted in the usual RGB colorspace. And this is what I added to vncrec-rgb
: outputting the movie frames as raw RGB triples for further processing using ffmpeg
or mencoder
.
Refer to the vncrec-rgb project webpage for vncrec-rgb
0.4.
Since this blog entry is still quite "fresh" and I'm doing screen recording for almost 2 years now, you made several mistakes. I'll explain why:
First of all, you're using HuffYUV. It's fast, but the output is uselessly huge. And it doesn't support any RGB colorspace at all, so there is some loss in the first place. You should use x264 (libx264rgb) with the ultrafast preset instead.
You also wrote that there are silent frame drops, which can't be true unless you ignore ffmpeg's console output completely. I think your problem is that the audio stream is simply not in sync with the video. You have to tell ffmpeg to sync it according to the timestamps.
So the final command line looks like this:
ffmpeg -y -f alsa -i default -r 30 -f x11grab -s 1920x1080 -i ${DISPLAY} -c:v libx264rgb -crf 0 -preset:v ultrafast -c:a pcm_s16le -af aresample=async=1:first_pts=0 out.mkv
I personally prefer Matroska instead of AVI, because it supports variable framerates and it doesn't use weird tricks beyond 2 GB. Using x264 as video codec, a CRF of 0 means lossless. However, you also can safely use -crf 10 without any visible artifacts but much smaller video output.
Also, you should use a framerate that matches your screen, if you care about smooth movements. In my example, my screen rate is 60 Hz, so I use 30 fps for recording.