Screencasting

Screencasting with glc

Sometimes you might wish to do some screencasts of your Linux games. Given that FFMPEG is slow, and that RecordMyDesktop doesn't really get on with Gnome 3, you might be stuck for a viable option. Yes Gnome 3 has its own screencast utility but it's not configurable in any way. Enter glc , a screencasting tool for OpenGL.

In today's little experiment, we will be using Fedora 15 64 bit with Gnome 3, and trying to record footage from Bethesda Softworks Oblivion using WINE 1.3.21 (32 bit). Oblivion has also be modded to use Morroblivion.


Prep work

Obviously you'll need to have installed Oblivion first - I'm running the Steam version. The first trick is just to make testing quicker - disable those pesky intro vids...

  1. Open Oblivion.ini
  2. Mine is at: /home/rob/Documents/Windows/My Games/Oblivion/Oblivion.ini
  3. Find the line:
    SIntroSequence=bethesda softworks HD720p.bik,2k games.bik,game studios.bik,Oblivion Legal.bik
  4. ...and replace it with:
    SIntroSequence=

You'll also want to install mplayer and ffmpeg - I recommend installing these from RPMFusion.


Installing glc

This is a doddle thanks to being scripted, though you may want to add your user as a sudoer so you can do the default install which makes life a lot easier, e.g. as root:

echo 'rob ALL=(ALL) ALL' >> /etc/sudoers

We'll need to install some dependencies (as root):

yum install cmake glibc-devel.i686 libX11.i686 libX11-devel.i686 libX11.x86_64 libX11-devel.x86_64 libXxf86vm.i686 libXxf86vm-devel.i686 libXxf86vm.x86_64 libXxf86vm-devel.x86_64 libglpng.i686 libglpng-devel.i686 libglpng.x86_64 libglpng-devel.x86_64 libpng.x86_64 libpng-devel.x86_64 libpng-static.x86_64 libpng.i686 libpng-devel.i686 libpng10.i686 libpng10-devel.i686 libpng10.x86_64 libpng10-devel.x86_64 mesa-libGL.x86_64 mesa-libGL-devel.x86_64 mesa-libGLU.x86_64 mesa-libGLU-devel.x86_64 mesa-libGL.i686 mesa-libGLU.i686 mesa-libGL-devel.i686 mesa-libGLU-devel.i686 alsa-lib.i686 alsa-lib-devel.i686 alsa-lib.x86_64 alsa-lib-devel.x86_64

Then change to the directory of your choice and download the required script, e.g.

cd /home/rob/Projects
mkdir glc
cd glc
wget https://github.com/nullkey/glc/raw/master/scripts/glc-build.sh

You will need to open the script up and change the variable ask-prompt to askprompt - it should be around line 17 somewhere. Then add executable permissions and run the script:

chmod a+x glc-build.sh
./glc-build.sh

This is the output of the script and shows that pretty much I went with the defaults:

[rob@dingo glc]$ sh glc-build.sh 
info  : Welcome to glc install script!
        Enter path where glc will be installed.
          (leave blank to install to root directory)
      > 
        Enter compiler optimizations.
          (-O2 -msse -mmmx -fomit-frame-pointer)
      > 
        Use git (y/n)
          (git contains latest unstable development version)
      > y

You should be able to do a simple test using:

glc-capture --out=glxgears-test.glc glxgears
glc-play glxgears-test.glc

Setting LD_LIBRARY_PATH

I found I needed to use the following command before starting glc-capture to successfully capture Oblivion in WINE, possibly because it's a 32 bit application and I'm on x86_64:

export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/lib32:/usr/lib64"

Note that glxgears does not need (and indeed does not like) LD_LIBRARY_PATH being set this way, and will output "Error: couldn't get an RGB, Double-buffered visual". If you have already used the above command and need to unset it (for example if you want to do a glxgears test), then do:

unset LD_LIBRARY_PATH

...or just use a different terminal window!


Capturing the video

To capture Oblivion using glc we can use the following command:

glc-capture --fps=15 --log=4 --log-file=/home/rob/Videos/Capture/glc.log --disable-audio --resize=0.5 --capture=back --draw-indicator --out=/home/rob/Videos/Capture/oblivion-test.glc wine C:/Program\ Files/Steam/Steam.exe -console -applaunch 22330 $@

This is recording at a modest 15fps and resizing the resolution (1280x1024) by 50%. It's not a requirement but you can tell glc to use the back buffer so you get a red square at the top left of the screen to let you know when it's recording. When you first try recording, I highly recommend adding a log file to help track down any problems.

To check out other available options, do:

glc-capture --help

Once we're done, we can check out our recording:

glc-play /home/rob/Videos/Capture/oblivion-test.glc

Sound problems

Updated: See "Sound problems revisited below"

I had been unable to get sound recording working reliably. It would record ALSA sound, but there was a significant delay before the sound started recording, leading to completely unsynchronised sound. To work around this I simply recorded the audio separately and used Pitivi later on to line up the audio / video, cropping the sections that were not required. To record the audio, you can open a second terminal and do:

ffmpeg -f alsa -ac 2 -i pulse -acodec pcm_s16le output.wav

Encoding using glc-play, mplayer and ffmpeg

I like webm. There, I said it. The quality's ok and it's patent free. So I'm encoding into webm. If you want to encode into h264 then there are lots of guides already on how to do this.

I'd seen yuv4mpeg pipes a couple of years back when trying out Cinelerra, but have never used them before... thanks to a post on the Ubuntu forums, I concocted this little bit of magic:

rm -f stream.yuv && \
mkfifo stream.yuv && \
glc-play /home/rob/Videos/Capture/oblivion-test.glc -y 1 -o - | \
mplayer -demuxer y4m -vo yuv4mpeg:file=stream.yuv -ao null -nosound -noframedrop -quiet - & \
ffmpeg -f yuv4mpegpipe -i stream.yuv -vcodec libvpx -r 15 -b 1400k -bt 4M -an -f webm -threads 2 capture.webm

It removes any existing stream, then pipes the glc-play output into mplayer that outputs to the yuv4mpeg stream. Following this, ffmpeg then takes the stream and converts it into a webm file.

At some point I'll do a more in depth guide on how to encode to webm/vp8, as I have lots of source material just sitting around.


Encoding using presets

Alternatively, if you want to create presets to make life easier, I found some useful information here and here and have modified the presets to give some additional options.

You can download the modified presets here.

You would then need to extract the files and copy them (as root) to /usr/share/ffmpeg/ after which you can then encode the video file using a preset instead, e.g.

cd /tmp/glc/
rm -f stream.yuv && \
mkfifo stream.yuv && \
glc-play oblivion-test.glc -y 1 -o - | \
mplayer -demuxer y4m -vo yuv4mpeg:file=stream.yuv -ao null -nosound -noframedrop -quiet - & \
ffmpeg -f yuv4mpegpipe -i stream.yuv -vcodec libvpx -vpre libvpx-720p-higher -r 24 -an -f webm -threads 2 output-video.webm

Sound problems revisited

Since writing the above, I have since found that sound recording seems to work ok if the sound output is set to ALSA with emulation, though other settings may work. Most importantly, I discovered that the sound lag seems to be present in glc-play, but if the audio is extracted out then it seems to be fine. This is the encoding script I am using now:

For capture:

#!/bin/sh

# Export LD_LIBRARY_PATH
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/lib32:/usr/lib64"

# Define filename / path and Steam application number
FILENAME="/tmp/glc/oblivion-test"
STEAMAPP="22330"

# To capture Oblivion using glc:
glc-capture --fps=15 --resize=0.5 --log=4 --log-file="$FILENAME".log --capture=back --draw-indicator --out="$FILENAME".glc wine C:/Program\ Files/Steam/Steam.exe -console -applaunch "$STEAMAPP" $@

For encoding:

#!/bin/sh
# Some command line magic to output to webm

# Define filename / path
FILENAME="/tmp/glc/oblivion-test"

# Output sound to ogg
glc-play "$FILENAME".glc -a 1 -o - | oggenc -q 10 - -o "$FILENAME".ogg

# Remove any existing YUV stream
rm -f "$FILENAME".yuv && \

# Make a new YUV stream
mkfifo "$FILENAME".yuv && \

# Out to YUV stream via mencoder into ffmpeg
glc-play "$FILENAME".glc -y 1 -o - | \
mplayer -demuxer y4m -vo yuv4mpeg:file="$FILENAME".yuv -ao null -nosound -noframedrop -quiet - & \
ffmpeg -f yuv4mpegpipe -i "$FILENAME".yuv -vcodec libvpx -vpre libvpx-720p-higher -r 24 -an -f webm -threads 2 "$FILENAME".webm

Editing and rendering

Pitivi

You can see an early test video I made with Pitivi here:

Example webm video of Oblivion (with Morroblivion mod) - 36.9MB

OpenShot

It occurred to me after doing the editing with Piviti that you could also use Openshot which is further along in development than Pitivi , has more features right now, and may be a little more stable

I've now done a couple of test videos using OpenShot, to install you will need the rpmfusion repository enabled. Install with:

yum install openshot frei0r-plugins

It seems very stable and the effects are much further along than Pitivi.

However, one thing I noticed was that I initially found it difficult to reach an acceptable file size vs compression for webm under OpenShot. The first way I found to resolve this was to output to a high quality version. See pictures one and two (for reference it works out around 1GB for 10 minutes at 1280x1024). I then used ffmpeg to reduce the filesize while still keeping the quality reasonable. Here's the command line I used:

#!/bin/sh

# Define filename / path and Steam application number
FILENAME="VideoName"

ffmpeg -i "$FILENAME".webm -vcodec libvpx -vpre libvpx-720p-higher -r 24 -f webm -acodec libvorbis -aq 8 -ac 2 -async 1 -threads 2 "$FILENAME"-Optimised.webm

Obviously this is using the presets method shown above.

However, I later discovered that although the OpenShot presets are in drop downs, you CAN manually enter a bit rate other than those in the drop down list. In this example, I have selected 1.5 MB/s, which gave me pretty much the same file size as the manual encoding example above, with no noticeable quality loss.


The test video

I've replaced the test video done in Pitivi with a newer (better) video made using OpenShot...

Alternatively, if your browser does not support the HTML5 tag / webm, you can download a copy by right clicking the following link and choosing "save as":

Example webm video of Oblivion (with Morroblivion mod) - 30.7MB

To play webm files outside of the browser, I recommend vlc.


References


Miscellaneous Notes

One of the original pages I read about using glc to record Wine games suggested:

glc-capture -s -b back --out="/home/username/Videos/capture.pid" wine-pthread "/usr/local/home/username/.wine/drive_c/Program Files/World of Warcraft/WoW.exe" $@
Now if we wanted to play that file we would run this:
glc-play /home/username/Videos/capture.pid

However, wine-pthread binary no longer exists...

See: http://forum.winehq.org/viewtopic.php?t=5450&view=next&sid=910f632bef4f83f43e358b33bcd23ece

With the most recent Linux kernels, pthreads is the ONLY thread method supported. Thus, there is no need for wine-pthreads anymore. I don't know how to access the current Wine threading methods, but they are all pthread based.
...and: http://www.winehq.org/announce/1.1.19
Changes since 1.1.18:

Alexandre Julliard (55):
      ntdll: Remove no longer used pthread_functions structure.
      loader: Don't bother checking for pthread.h existence, we require it anyway.

Another page suggested how to do ffmpeg only screencasting:

ffmpeg -f alsa -ac 2 -i pulse -f x11grab -r 24 -s 1280x1024 -i :0.0 -acodec pcm_s16le -vcodec libx264 -vpre lossless_ultrafast -threads 0 output.mkv

From this I took the audio part to workaround the sound recording problems:

ffmpeg -f alsa -ac 2 -i pulse -acodec pcm_s16le output.wav