Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
recordscreen: A bash script for timelapse recordinging two separate X displays, and creating a picture-in-picture overlay with one display
#!/bin/bash
if [ ! $# -eq 2 ] ; then
echo "Usage: ./recordscreen delay outputfolder"
exit
fi
if [ ! -d $outputFolder ] ; then
echo "Output folder does not exist"
exit
fi
# $1:output
function captureScreenDump {
xwd -root -out $1
}
# $1:input-file $2:output-file
function prepareThumbnail {
convert $1 -thumbnail 300x300 -bordercolor "#881111aa" -border 2 \
\( +clone -background black -shadow 100x3+2+2 \) \
+swap -background none -layers merge +repage $2
}
# $1:left-image $2:right-image $3:output-frame
function prepareFinalFrame {
pictureInPictureOffset=+1588+837
convert -composite $1 $2 -geometry $pictureInPictureOffset $3
}
# $1:counter $2:folderOuput
function doFrameCapture {
# Filenames for left and right screen
outfile=`printf '%.5d' $1`-`date +"%Y-%m-%d-%s"`
left=${2}/left/${outfile}
right=${2}/right/${outfile}
# Capture both screens at the same time
(DISPLAY=:0.0 captureScreenDump ${left}.xwd && pid1=$!) &
(DISPLAY=:0.1 captureScreenDump ${right}.xwd && pid2=$!)
wait $pid1 $pid2
# Prepare right screen as thumbnail
thumbnail=${right}-thumbnail
prepareThumbnail ${right}.xwd ${thumbnail}.png
# Create final frame from left frame and thumbnail of right frame
outfileFinal=${2}/frames/`printf '%.5d' $1`
prepareFinalFrame ${left}.xwd ${thumbnail}.png ${outfileFinal}.png
# Cleanup:
rm $left.xwd $right.xwd $thumbnail.png
}
################### PROGRAM CODE STARTS ###################
delay=$1
outputFolder=$2
mkdir $outputFolder/{left,right,frames}
curr=0
while sleep $delay;
do
((curr++))
(doFrameCapture $curr $outputFolder &)
done
#################### ----------------- ####################
#!/bin/bash
# Setup:
####################
# Automatic setup detection using xrandr
xrandrOutput=`xrandr --query`
leftGeometry=`echo "$xrandrOutput" | grep -P "\sconnected" \
| grep -oP '\d+x\d+\+0\+\d+'`
rightGeometry=`echo "$xrandrOutput" | grep -P "\sconnected" \
| grep -oP '\d+x\d+\+\d{2,}\+\d+'`
primaryGeomtry=`echo "$xrandrOutput" | grep -P "\sconnected primary" \
| grep -oP '\d+x\d+\+\d+\+\d+'`
if [[ "$primaryGeomtry" == "$leftGeometry" ]] ; then
mainMonitor=left
elif [[ "$primaryGeomtry" == "$rightGeometry" ]] ; then
mainMonitor=right
else
echo "Failed to detect main monitor"
fi
leftMonitor=${leftGeometry%%+*}
rightMonitor=${rightGeometry%%+*}
pipSize=340x340
pipOffset=+30+20
# Implicit variables
leftMonitorWidth=${leftMonitor%x*}
echo "leftMonitor: " $leftMonitor
echo "rightMonitor: " $rightMonitor
echo "pipSize: " $pipSize
echo "pipOffset: " $pipOffset
echo "mainMonitor: " $mainMonitor
########################
if [[ ! "$mainMonitor" == "left" ]] && \
[[ ! "$mainMonitor" == "right" ]] ; then
echo "Bad mainMonitor variable"
exit
fi
if [ ! $# -eq 2 ] ; then
echo "Usage: ./recordscreen delay outputfolder"
exit
fi
if [ ! -d $outputFolder ] ; then
echo "Output folder does not exist"
exit
fi
gsettings set org.gnome.desktop.sound event-sounds false
# $1:output
function captureScreenDump {
xwd -root -out $1
}
# $1:input-file $2:output-file
function prepareThumbnail {
if [[ "$mainMonitor" == "left" ]] ; then
geometry=${rightMonitor}+${leftMonitorWidth}+0
else
geometry=${leftMonitor}+0+0
fi
convert $1 -crop $geometry -thumbnail $pipSize \
-bordercolor "#881111aa" -border 2 \
\( +clone -background black -shadow 100x3+2+2 \) \
+swap -background none -layers merge +repage $2
}
# $1:captured-image $2:pip-thumbnail $3:output-frame
function prepareFinalFrame {
geometry=
if [[ "$mainMonitor" == "left" ]] ; then
geometry=${leftMonitor}+0+0
else
geometry=${rightMonitor}+${leftMonitorWidth}+0
fi
convert -crop $geometry ${1} ${1}.tmp.xwd
convert -composite ${1}.tmp.xwd $2 -gravity SouthEast \
-geometry $pipOffset $3
rm ${1}.tmp.xwd
}
# $1:counter $2:folderOuput
function doFrameCapture {
# Filenames for capture and right screen
outfile=`printf '%.5d' $1`-`date +"%Y-%m-%d-%s"`
capture=${2}/capture/${outfile}
pip=${2}/pip/${outfile}
# Capture both screens at the same time
captureScreenDump $capture.xwd
prepareThumbnail $capture.xwd $pip.png
# Create final frame from left frame and thumbnail of right frame
outfileFinal=${2}/frames/`printf '%.5d' $1`
prepareFinalFrame ${capture}.xwd ${pip}.png ${outfileFinal}.png
# Cleanup:
rm -f $capture.xwd $pip.png
}
function finalize() {
rm -f $outputFolder/{capture,pip}/*
rmdir $outputFolder/{capture,pip}
gsettings set org.gnome.desktop.sound event-sounds true
exit
}
trap finalize SIGINT SIGTERM
################### PROGRAM CODE STARTS ###################
delay=$1
outputFolder=$2
curr=0
if [ -e $outputFolder/frames ] ; then
lastFrame=`ls -1 $outputFolder/frames/ | tail -n 1`
curr=`echo ${lastFrame%.*} | sed 's/^0*//'`
while true; do
read -p "Recording in progress (currently $curr frames)
Do you wish to continue at frame "$((curr+1))"? [y/n] " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
fi
if [ ! -e $outputFolder/capture ] ; then mkdir $outputFolder/capture ; fi
if [ ! -e $outputFolder/pip ] ; then mkdir $outputFolder/pip ; fi
if [ ! -e $outputFolder/frames ] ; then mkdir $outputFolder/frames ; fi
while sleep $delay;
do
((curr++))
(doFrameCapture $curr $outputFolder &)
done
#################### ----------------- ####################

why don't you just ffmpeg -s 1280x720 -f x11grab -i :0.0+100,100 -filter:v "setpts=PTS/30" -r 30 though?

anko commented Sep 11, 2014

@phiresky
Does that capture multiple screens?

There's a great script called ffcast that automates selecting an area and recording it, with x11grab as you mentioned. I summarised how to use it and convert the results to GIF here. (I don't know if my method works with multiple screens though...)

Why using xwd -root -out foo.xwd instead of import -window root foobar.png? import is from ImageMagick, the same package that provides convert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment