Introduction
If you don't care about "why and how", just skip to the end of the article where the script is or go grab it on github.
I'm a bit pathologic when it comes to the tools I use on a day to day basis and I often want as much control as I can have.
I work as a full stack developer and lately, with my team, we decided that we wanted to demonstrate all the features we are releasing to other teams and screencasts can be a great medium for that purpose.
Tools already exist to capture screencasts and some of them are really close to what I wanted but I'm using i3 as a window manager, with multiple screens and no floating windows. Tools like peek for example don't work really well with that configuration.
So I decided to take the dirty path and take advantage of the first unix principle: "Make each program do one thing well".
In this case here is what I expect from this rule: each brick I need to build my wall probably already exists (spoiler: of course they do).
What I need:
- a tool able to capture a video from part of my screen, given coordinates
- a tool to designate coordinates
- a tool to build interaction upon
The tools
- FFmpeg, the swiss army knife of video
- xdotool, a small program allowing to manipulate windows, mouse, and keyboard in a X environment
- dmenu, a dynamic menu for X
I already used xdotool
and dmenu
in a lot of productivity scripts, I may present more about them in other articles.
The solution
- On the first launch, the script uses
dmenu
to guide the user in selecting the coordinates for her capture, its output is not used, it just serves for talking with the user and inserting "breakpoints" in the script -
xdotool
is used to grab mouse coordinates (top left corner then bottom right corner) - Using that coordinates, the width and height are calculated
-
ffmpeg
is launched with itsx11grab
input to capture the desktop. It is launched has a background job and its PID is saved in a file - When launched a second time, the script detects that the PIDFILE is there, verifies if the process is still running, kills it gently and displays the captured video.
I've bound the script to a keyboard shortcut in my i3
config file so the calls to echo
in the script are just for debugging.
#!/bin/bash
PIDFILE=${HOME}/.screencast_pid
if [ -f ${PIDFILE} ]; then
PID=$(cat ${PIDFILE})
if [ -n "$(ps -p ${PID} -o pid=)" ]; then
echo "Screencast in progress" | dmenu
WD=$(readlink -f /proc/${PID}/cwd)
OUTFILE=${WD}/output.mp4
kill ${PID}
rm ${PIDFILE}
vlc ${OUTFILE}
exit 1
else
echo "wrong pidfile"
rm ${PIDFILE}
fi
fi
get_mouse_location() {
echo "Go to $1 then press Enter." | dmenu > /dev/null
xdotool getmouselocation
}
tlc=$(get_mouse_location "top left corner")
brc=$(get_mouse_location "bottom right corner")
top=$(echo ${tlc} | sed -e "s/.*y:\([0-9]\+\).*/\1/")
lef=$(echo ${tlc} | sed -e "s/.*x:\([0-9]\+\).*/\1/")
bot=$(echo ${brc} | sed -e "s/.*y:\([0-9]\+\).*/\1/")
rig=$(echo ${brc} | sed -e "s/.*x:\([0-9]\+\).*/\1/")
width=$(expr ${rig} - ${lef})
height=$(expr ${bot} - ${top})
echo "Do screencast ${width}x${height} from top: ${top} left: ${lef} to bottom: ${bot} right: ${rig}"
ffmpeg -v 8 -video_size ${width}x${height} -framerate 10 -y -f x11grab -i :0.0+${lef},${top} output.mp4 &
FFMPEG_PID=$!
echo ${FFMPEG_PID} > ${PIDFILE}
Ideas for enhancement
- Let the user decide what to do with the video (display it, move it in a specific folder, upload it, remove it...)
- Allow capturing whole screen by giving more than one choice in the calls to
dmenu
(and even allow cancelling)
And you, do you like crafting your own walls with existing bricks? What is in your toolbox? Also, let me know if you find this kind of post useful.
PS: You'll find the tools I'm talking about here
Top comments (0)