GIF screencasting; the UNIX way
OK then
I started ffcast
, did vim
, quit ffcast
, then convert
ed .avi
→.gif
.
I ran the recording commands in another terminal. Polished script for your $PATH
at the end of this answer.
What happened?
Capturing
FFcast helps the user interactively select a screen region and hands over the geometry to an external command, such as FFmpeg, for screen recording.
ffcast
is the glorious product of some hacking at the Arch Linux community (mainly lolilolicon). You can find it on github (or in the AUR for Archers). Its dependency list is just bash
and ffmpeg
, though you'll want xrectsel
(AUR link) for interactive rectangle selection.
You can also append ffmpeg
flags right after the command. I set -r 15
to capture at 15 frames per second and -codec:v huffyuv
for lossless recording. (Play with these to tweak the size/quality tradeoff.)
GIFfing
ImageMagick can read .avi
videos and has some GIF optimisation tricks that drastically reduce file size while preserving quality: The -layers Optimize
to convert
invokes the general-purpose optimiser. The ImageMagick manual has a page on advanced optimisations too.
Final script
This is what I have in my $PATH
. It records into a temporary file before converting.
#!/bin/bash
TMP_AVI=$(mktemp /tmp/outXXXXXXXXXX.avi)
ffcast -s % ffmpeg -y -f x11grab -show_region 1 -framerate 15 \
-video_size %s -i %D+%c -codec:v huffyuv \
-vf crop="iw-mod(iw\\,2):ih-mod(ih\\,2)" $TMP_AVI \
&& convert -set delay 10 -layers Optimize $TMP_AVI out.gif
Thanks to BenC for detective work in figuring out the correct flags after the recent ffcast
update.
If you'd like to install the dependencies on a Debian-based distro, Louis has written helpful installation notes.
For me, the answer was to use ffcast
with ffmpeg
like so:
ffcast -w % ffmpeg -f x11grab -show_region 1 -framerate 20 -video_size %s -i %D+%c -codec:v huffyuv -vf crop="iw-mod(iw\\,2):ih-mod(ih\\,2)" out.avi
I then used ffmpeg
to do the conversion from avi to gif - it's very fast and it keeps the framerate intact:
ffmpeg -i out.avi -pix_fmt rgb24 out.gif
Lastly I used convert in the same way as @anko's answer to optimise the gif, but I set a limit on resource usage to stop convert
exiting with a killed
message, and I removed the delay as ffmpeg
has already handled that:
convert -limit memory 1 -limit map 1 -layers Optimize out.gif out_optimised.gif
for my setup(ubuntu 16.04), ffcast doesn't work well as it's not updated on github for quite a while.
so I put up a script using slop(https://github.com/naelstrof/slop) and ffmpeg.
an example:
#!/bin/bash
read -r X Y W H G ID < <(slop -f "%x %y %w %h %g %i")
TMP_AVI=$(mktemp /tmp/outXXXXXXXXXX.avi)
ffmpeg -s "$W"x"$H" -y -f x11grab -i :0.0+$X,$Y -vcodec
huffyuv -r 25 $TMP_AVI
convert -set delay 5 -layers Optimize $TMP_AVI out.gif
Update:
Code updated, ffmpeg returns exit code 2 that prevents convert
from executing as mentioned by Rub. After recording, hit ctrl+C will exit ffmpeg and run convert
to generate the out.gif.