Screencasting with FFmpeg, jack_capture and Xephyr

Introduction

Not satisfied with the quality of the screencasts made with recordMyDesktop I started looking for an alternative that might yield better results, especially the video part. The JACK support of recordMyDesktop is a big plus and quite solid too but recordMyDesktop converts all video to Theora only and this has proved inconvenient when uploaded to a webservice like YouTube. The video quality just degraded too much.
So I needed a different toolset. For the video part I chose FFmpeg for its unrivaled flexibility and support for input and output formats. FFmpeg also has JACK support but I found the JACK input client to be too xrun prone so for the audio part I chose jack_capture, a lightweight, flexible commandline driven recording tool.
To prevent webservices like YouTube having to downscale or upscale your videos, which deteriorates the quality of your videos drastically, you can optionally run the whole screencast session in a nested X server with the help of Xephyr.

Requirements

  • A recent version of FFmpeg compiled with support for the h.264 protocol
  • Xephyr [optional]
  • A video editor, I use OpenShot or kdenlive myself
  • A screen with a minimal horizontal resolution of 1280 pixels

Screencast script

I use a simple script like this:

#!/bin/bash

DATE=`date +%Y%m%d`
TIME=`date +%Hh%M`

# Start screencast
xterm -e jack_capture -b 24 $HOME/Screencasts/screencast_audio_$DATE-$TIME.wav &
ffmpeg -an -f x11grab -r 30 -s 1280x720 -i 0:0 -vcodec libx264 -vpre lossless_ultrafast -threads 4 $HOME/Screencasts/screencast_video_$DATE-$TIME.mkv

killall jack_capture

You might need to adjust the number of threads for the ffmpeg -threads parameter to match the number of cores of your CPU. If unsure, set it to 0, ffmpeg should then set the numbers of threads automatically.

jack_capture by default captures all the audio that is connected to system:ouput. If you want to be able to manually make connections to jack_capture with jack_connect, qjackctl or whatever, you have to pass it the -mc option (you need at least version 0.9.58 for this)

Optional Xephyr script

Set up a Xephyr nested X server with a resolution of 1280×720 as this resolution yields the best result when uploading the final video to a webservice like YouTube. I use a little script for this:

#!/bin/bash

# Set up nested X server
Xephyr -keybd ephyr,,,xkbmodel=evdev -br -reset -host-cursor -screen 1280x720x24 -dpi 96 :2 &
sleep 3
export DISPLAY=:2.0
/etc/X11/Xsession &

As you can see I set up a session by calling /etc/X11/Xsession. In Ubuntu >= 9.10 this starts up a new fresh Gnome session and because I use IceWM for my main session in which I run Xephyr this works very well. If you're using Gnome as your DE using /etc/X11/Xsession won't work properly so in that case you will have to resort to a different start-up option. This also holds for distributions that don't use /etc/X11/Xsession.

TODO:other distros

After you ran this Xephyr script, you should run the above screencast script, taking care of making the following changes to it:

  • add the line “export DISPLAY=:2.0” after the TIME line.
  • change -i 0:0 ffmpeg option to -i :2.
  • add the -display 0:0 option to the xterm line (so it won't appear in your screencast).

Within the Xephyr session I also use a plain cursor theme without drop shadow because ffmpeg doesn't capture the drop shadow properly. As of FFmpeg revision 25690 this has been fixed.

Editing, rendering and uploading to a webservice

Now you have two separate files, an .mkv and a .wav file and because jack_capture was started right after ffmpeg audio should be no more out of sync then just a few millisecs. You can now edit the audio and video parts to your liking:

  • Edit the .wav file in Audacity or Rezound if necessary. I use some extra gain and compression if necessary.
  • Import the two files in OpenShot and crop start and end to your liking.
  • With VLC I made some stills from the video file and with Gimp I edited these to create the titling.
  • Create transitions, fade-ins and fade-outs to your liking with OpenShot.

For rendering/exporting I use the following settings in OpenShot:

  • Video: 1280×720, 30 fps (this should match the settings of ffmpeg), mp4 videoformat, 40 Mb/s (Blu-ray quality), libx264 videocodec.
  • Audio: mp3 (libmp3lame), 256 Kb/s and 44.1 Khz sample rate.

Now you can upload the resulting mp4 file to a webservice. The settings I've used will yield optimal results for YouTube.

Examples

wiki/screencasttutorial.txt · Last modified: 2013/06/02 15:45 (external edit)