Make a screencast with ffmpeg
Several applications to record your desktop exist, but ffmpeg can do it all by itself, via its
x11grab format specifier. But there were some challenges:
- Sound: If you use pulseaudio or jack audio, other solutions apply. But with plain ALSA it isn't so easy to simply record what the computer sends to your speakers. In the end I just plugged the cable that goes from Line Out (usually to my speakers) back into Line In. Then (via
alsamixer, press F4 to get capture channels) I had to activate the main CAPTURE channel and set the Input Source to Line. Surprisingly, this did not result in feedback. I had to fiddle with the volumes to avoid distortion and background hum. It's not HiFi, but good enough.
- Performance: What ffmpeg does when recording your screen is to transcode the X11 video into compressed output, based on file extension. But I wanted to record a game, and this proved to be too resource-intensive in combination, esp. if I want ffmpeg to produce high quality output. So I recorded the session in raw, uncompressed format. Be aware, your hard drive will fill up really quickly (and a slow hard drive might incur another performance penalty): a 5 minute 1152x864px video has 7.5GB.
In the end I changed the screen resolution of the whole desktop, started the game in fullscreen mode and told ffmpeg to record that:
$ sleep 5 ; ffmpeg -f alsa -i hw:0 -f x11grab -r 25 -s 1152x864 -i :0.0 -c:v ffvhuff -c:a flac output1.mkv
Since MKV is a container format, it can also contain uncompressed video formats.
Trim first - example:
$ ffmpeg -i output2.mkv -t 00:02:36 -acodec copy -vcodec copy output2-a.mkv
It starts at zero by default (if not, use the
-ss option) and uses the first 2min 36s.
Next one needs to create a text file (let's call it list.txt) with a list of files to be concatenated:
file 'output1-a.mkv' file 'output2-a.mkv'
and then concatenate like this:
$ ffmpeg -f concat -safe 0 -i list.txt -c copy output-full.mkv
Lastly, I make a high quality two-pass encoding of the resulting file. Please note that, although I chose the MKV format again, this is a totally different codec with much smaller file size. I also must first concatenate the videos into their final form, and then transcode.
$ ffmpeg -i output-full.mkv -an -vcodec libx264 -pass 1 -preset veryslow -threads 0 -b 1000k -x264opts frameref=15:fast_pskip=0 -f rawvideo -y /dev/null $ ffmpeg -i output-full.mkv -acodec aac -ab 64k -vcodec libx264 -pass 2 -preset veryslow -threads 0 -b 1000k -x264opts frameref=15:fast_pskip=0 output-final.mkv
Note that the sound is only transcoded during the second pass (to 64kb AAC).
The uncompressed 7.5GB file (~5 minutes) has shrunken to a very reasonable 38.8MB at 1000kb/s while keeping the original resolution of 1152x864px. The quality is very good, I can't spot any difference to the original: