Eric Radman : a Journal

Screencasting with OpenBSD

Notes on making a screen capture.

Audio Input

Chances are you are using a USB microphone, and it will appear as an audio device. Here is the dmesg for my mic by ART

uaudio0 at uhub0 port 2 configuration 1 interface 0 "M-One USB" rev 1.10/0.01 addr 2
uaudio0: audio rev 1.00, 8 mixer controls
audio1 at uaudio0

audioctl can read off all of the specific characteristics of this device

$ audioctl -f /dev/audio1 | grep record
mode=play,record
record.rate=48000
record.channels=1
record.precision=16
record.bps=2
record.msb=1
record.encoding=slinear_le
record.pause=0
record.active=0
record.block_size=1960
record.bytes=0
record.errors=0

Now test the recording from the second audio device using aucat

aucat -f snd/1 -o file.wav

If the device also has a headset audio can be played through the same device.

aucat -f snd/1 -i file.wav

Screen Capture using Xephyr

Xephyr is perhaps the easiest way to run a dedicated X for recording

Xephyr -ac -br -noreset -screen 1280x720 :1 &
DISPLAY=:1 xsetroot -solid steelblue &
DISPLAY=:1 cwm &

Now we can start a terminal with CM-Return CM-f Capture works in exactally the same way. This command tries to maintain 12fps.

ffmpeg -f sndio -i snd/1 -y -f x11grab -r 12 -s 800x600 -i :1.0 -vcodec ffv1 -acodec copy ~/out.avi

To capture keyboard and mouse input press Ctrl+Shift This is very handy for using navigating a window manager in the nested X session.

Arranging Windows

I have sometimes found it helpful to launch applications and arrange them in a specific way. This will open up a web browser listing the current directory and position windows using xdotool

DISPLAY=:1 midori "file:///`pwd`" &
sleep 2
DISPLAY=:1 xdotool search --name "xterm" windowmove 0 0
DISPLAY=:1 xdotool search --class "midori" windowmove 400 0
DISPLAY=:1 xdotool search --class "midori" windowsize 400 576

This will position the window precisely so that it appears to be in a tmux window on the right.

Audio/Video Sync

If you find that the audio is way out of sync with the video, you can ajust the start using the -ss before the audio input to specify the number of seconds to delay. My final recording command line, that delays the audio by 0.5 seconds, writing 12fps

ffmpeg -ss 0.5 -f sndio -i snd/1 -y -f x11grab -r 12 -s 800x600 -i :1.0 -vcodec ffv1  -acodec copy ~/out.avi

Taking Screenshots

Grabbing a screenshots on Xvfb server is easily accomplished with ImageMagick's import command

DISPLAY=:1 import -window root screenshot.png

Audio Processing and Video Transcoding

To trim the beginning and end of the recording specify the start time and duration using the encoding option copy

ffmpeg -i interactive-sql.avi \
    -vcodec copy -acodec copy \
    -ss 00:00:00 -t 00:09:45 \
    interactive-sql-trimmed.avi
mv interactive-sql-trimmed.avi interactive-sql.avi

Setting the gain correctly is very important with an analog mixer, but if USB mics may not be a gain setting: after recording adjust the levels afterwards using a utility such as normalize.

ffmpeg -i interactive-sql.avi -c:a copy -vn audio.wav
normalize audio.wav

Next merge the audio back in again

ffmpeg -i interactive-sql.avi -i audio.wav \
    -map 0:0 -map 1:0 -c copy interactive-sql-normalized.avi

The final step is to compress the screencast for distribution. Encoding to VP8/Vorbis is easy:

ffmpeg -i interactive-sql-normalized.avi -c:v libvpx -b:v 1M
    -c:a libvorbis -q:a 6 interactive-sql.webm

H.264/AAC is tricky. For most video players the color space needs to be set to yuv420p. The -movflags puts the index data at the beginning of the file to enable streaming/partial content requests over HTTP:

ffmpeg -y -i interactive-sql-normalized.avi -c:v libx264 \
    -preset slow -crf 14 -pix_fmt yuv420p -movflags +faststart \
    -c:a aac -q:a 6 interactive-sql.mp4