Screencasting In Ubuntu

I have been doing some screencasting over the past year or so. Some of it directly, some it scraping recordings out of things like Elluminate or other web conferencing tools. It's been a somewhat long process to come up with something that works well for me, so I thought it was worth sharing.

I've tried all the tools that should make screencasting easy in Ubuntu (RecordMyDesktop, Istanbul, Cankiri, and XVidCap), and I've found them all lacking (to say the least). If they work at all, they are still beset by a host of problems: unreliable recordings, crashing in the middle of recordings, unsynced video and audio, using way too much CPU/memory/disk while recording, restrictive file format choices, etc. If you find one that works well or think one of the ones I mentioned has been updated to deal with its challenges let me know.

So, being a long-time Linux hacker, I took to the command line and sought to assemble a set of tools that actually worked and then develop a script to rule them all. Some of the goals I have in the process:

  • Low use of resources during the recording. Frequently I am recording something that requires a lot of resources itself, and I want to minimize how much it fights with the recording.
  • Keep the intermediate artifacts. I want the intermediate video/audio recording to stick around and I'll delete them when I'm sure I don't need them. Some of the "easy tools" would crash not during the recording, but during the post-processing and would lose or corrupt the sources in the process.
  • Timed recording. Sometimes I want to start a longish recording and walk away (or go to bed), but I don't want it to record the entire time until I get back to the computer. This is especially useful when scraping long recordings out of another platform.
  • Direct support for PulseAudio. When I'm scraping recordings, I don't want to record an audio input, I want to record the audio output that goes with the recording. PulseAudio makes that easy since through the "PulseAudio Volume Chooser" I can select the Monitor of Internal Audio as the default audio source.
  • Final output of the recording process should be in a format that is easily editable with a variety of tools. I tend to use Avidemux for simple cleanup of recordings, but the format should be mainstream enough that any editing tool should work.
  • Final output of the entire process should be an H.264 file in MP4 format that will easily play through current versions of Adobe Flash and be compatible with a simple video player like FlowPlayer so that the videos can be posted directly to websites.

The Script

Okay, with all that in place and lots of experimenting, I built this script:

screencast.sh

I keep it in a directory where I want all the source files for the screencast to show up when I'm done. The script does require a few tools be installed:

  • grep, head, sed - standard Linux utilities (installed by default)
  • xdpyinfo - display information utility for X (installed by default)
  • ffmpeg - record video and assemble media (install package 'ffmpeg')
  • pacat, parec - PulseAudio play and record tools (install package 'pulseaudio-utils')
  • sox - audio processing (install package 'sox')

So, to make this script work, you need to install the following additional packages: ffmpeg, pulseaudio-utils, sox, ubuntu-restricted-extras (for all the codecs). You should also install pavucontrol which gives you the PulseAudio controls I mentioned earlier.

Recording The Screencast

With the required utilities installed and the script ready to go, you should run a short test recording to make sure you are getting appropriate video results and the right audio stream.

There are some command line options for the script to adjust the area of the screen to capture, the frame-rate to capture, the quality of the capture, to set up a timed recording. The defaults will capture your whole screen until you quit the script. You can also set the basename for all recording output, or just let it use 'capture' as the default. "./screencast.sh -h" will show you the syntax.

If you run a timed recording, it will finish when the time has expired. If you are running an open-ended recording (the default), just go back to the terminal window where you have the script running and hit Enter to stop the recording. When you end the recording, it will do some immediate post-processing.

The initial recording will leave a file called capture.mpeg that contains the combined audio and video file using mpeg2 video and mp2 audio in an mpeg container. Check this file in your movie player to see if you are getting a good recording.

If you aren't getting the right audio stream, go run the "PulseAudio Volume Control" (it should be in the "Sound & Video" menu) and go to the "Input Devices" tab. Change the "Show" choice at the bottom of the window to "All Input Devices" and now you can adjust the selections accordingly. For the device you want to capture, you should click the "Set as fallback" button (the green circle/checkmark thing) and now that should be the source your next recording will use. With the recording in-progress, you should be able to go to the "Recording" tab and see a parec process listed and you can make changes to that specific stream if you want. However, if you stop and start over you'll have to make those changes again every time.

Once you have a successful test that is capturing the right video and audio, you should be ready to go and make your recording.

The recordings do still use a fairly large amount of disk space. An hour long recording of a large resolution screen with a high frame rate can a recording file that is several GB in size, so make sure you have plenty of free space available for your recordings. This amount of space is a tradeoff I am willing to make in order to keep CPU use low during recordings.

Now you can use the capture.mpeg file as source for your favorite video editor.

Editing The Screencast

Usually the only things I am looking to do during editing are to trim out any junk at the beginning and end, and perhaps any unneeded/unwanted portions in the middle. As long as all I'm looking to do is make cuts, I can do everything I want in Avidemux (just install the avidemux package for this).

Using Avidemux, I configure for the following:

  • Video Codec set to "MPEG-4 AVC (x264)", which is the H.264 encoder.
  • Configuring the Video Codec I set the Encoding Mode to "Two Pass - Average Bitrate" and the Average bitrate to 750 kb/s. (you can increase this if the screencast is high-res or the images are quite active, but it will increase the final file size.) Everything else there I take the defaults.
  • For Video Filters, I use the following:
    • Crop : to eliminate anything out of the picture I don't want. I especially use this when I'm scraping a recording out of some other player.
    • MPlayer Resize : For most screencasts, I resize them down to 640x480, especially if they are mostly just slides. If it's a more detailed or more active video then larger might be appropriate, but again in will make the resulting file larger.
    • Resample FPS : For most screencasts, I drop this down to 10 frames per second. Again, if your video is more active, you may want a higher number of even leave it at 24.
    • MPlayer Delogo : I only use this filter if I need to blur out part of the video image. For example, if there is a logo to get rid of or if there is call-in information displayed on the title slide. If I only need to do this for some of the video (for example, info on the title slide I want to obscure), then I use the "Partial" button to configure the specific frames that I want blurred.
  • Audio Coded set to "AAC (Faac)".
    Configuring the Audio Codec, I set the bitrate to 96kb/s if it's just voice. If it is a richer audio source, I set it to 128kb/s.
  • For Audio Filters, I set the following:
    • Set the Mixer to "Mono" if it's just voice. Leave as "Stereo" if it's a richer audio source.
    • Enable Dynamic range compression.
    • Set the Gain mode to "Automatic (max -3dB)
  • Finally, I set the file format to MP4.

That's a lot of configuration and I don't want to have to do that every time I edit, so I save all this into a custom profile. You can do this with the "Save Project As..." menu option. Edit the resulting file and remove all the project-specific data, such as source filename and any edits, and then put the resulting file into "~/.avidemux/custom/screencast.js". Now you can apply those settings anytime you start editing by selecting that file out of the "Custom" menu in Avidemux. You should apply this file after you load your source video file. Here is my current screencast.js file. The format does change in different releases. This file is from Avidemux 2.5.3 – it may not work in other versions, so just follow the steps above to create a similar file for your version.

So, with all the configuration loaded, now it's time do the actual editing. First I need to go adjust my video filters:

  • Set the cropping for this specific video.
  • Make any changes to resizing and resampling for this specific video.
  • Set up blurring out any logos or other info as needed.

Now I go through and make my cuts to trim off unwanted portions at the beginning, end, and anywhere in between.

With that done, I now do a "Save" and select the .MP4 container type. This will then transcode the edited video and deliver the resulting file. This may take quite a while and will use the CPU fairly heavily, so start this job when this won't be a problem.

Final Post-Production on The Screencast

There are a few final post-production steps for finishing the screencast. One is that, by def ault, the meta-data in the MP4 container is written at the end of the file. Players can't start playing the file until they have this metadata, so when used in a web page, it means the movie can't play until it finishes downloading. By moving the metadata to the front, the file can start playing as soon as it starts downloading – much better experience, especially with large files. Another is that you sometimes want/need a static image as a splash screen for the video. Depends on where you are planning on posting the video and so forth.

So, I have another script that will post-process the MP4 file to take care of these things: mp4cleanup.sh

For this script to work, you just need ffmpeg installed. Just give it the base name of your .mp4 file and it will modify the MP4 file as needed and will generate a PNG splashscreen image. If you also want it to make a splashscreen that has a "play" button on it, put this image in the same directory and it will automatically make one for you: play.png as long as you have the imagemagick package installed.