Skip to content

Instantly share code, notes, and snippets.

@DanielFGray
Last active February 24, 2016 22:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielFGray/334168827097f2d11729 to your computer and use it in GitHub Desktop.
Save DanielFGray/334168827097f2d11729 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
declare file="$(date +%F-%s).webm"
declare window=false
declare region=false
declare duration
declare delay=0
declare verbose
declare -A dimensions
usage() {
more <<'HELP'
'Usage: record [OPTIONS]
-h this help
-f specify file name [defaults to "$(date +%F-%s).webm"]
-F specify file name and overwrite if exists
-d specify duration
-D specify delay
-w select window
-s draw selectable region
-v show verbose output from ffmpeg'
HELP
}
err() {
echo -e "\e[31m$1\e[0m" >&2
}
die() {
if [[ -n "$1" ]]; then
err "$1"
fi
exit 1
}
has() {
command -v "$1" &> /dev/null
}
ask() {
read -n1 -p "$* " ans
echo
[[ "${ans^}" == 'Y' ]]
}
delay() {
for (( i=delay; i>0; --i )) ; do
echo -ne "$i.. \r"
sleep 1
done
echo -ne "recording \r"
}
getdimensions() {
if [[ "$window" == true ]]; then
local xwininfo x y w h
echo -ne 'click a window\r'
xwininfo=$(xwininfo)
read -r x y w h < <(awk -F':' '/Absolute upper-left X/ { x=$2 }
/Absolute upper-left Y/ { y=$2 }
/Width/ { w=$2 }
/Height/ { h=$2 }
END { print x, y, w, h }' <<< "$xwininfo")
dimensions=( ['x']="$x" ['y']="$y" ['w']="$w" ['h']="$h" )
elif [[ "$region" == true ]]; then
has xrectsel || die 'xrectsel required for -s'
echo -ne 'select a region\r'
#TODO: don't use eval
eval "dimensions=( $(xrectsel "['x']='%x' ['y']='%y' ['w']='%w' ['h']='%h'") )"
else
scrsize=$(xdpyinfo | awk '/dimensions/{print $2}')
dimensions=( ['x']='0' ['y']='0' ['w']="${scrsize%%x*}" ['h']="${scrsize#*x}" )
fi
}
record-byzanz() {
#TODO: remove byzanz altogether in favor of plain ffmpeg
byzanz-record \
--duration="${duration:-10}"\
--x="${dimensions['x']}"\
--y="${dimensions['y']}"\
--width="${dimensions['w']}"\
--height="${dimensions['h']}"\
"$file" &&
echo "saved as $file"
}
record-ffmpeg() {
local loglevel size offset
loglevel='panic'
[[ -n $verbose ]] && loglevel='panic'
size="${dimensions['w']}x${dimensions['h']}"
offset="${DISPLAY}.0+${dimensions['x']},${dimensions['y']}"
ffmpeg -y -loglevel "$loglevel" -f x11grab -s "$size" -i "$offset" ${duration:+-t $duration} \
-c:v libvpx -crf 12 -s "$size" -b:v 1200k \
-preset veryslow \
-b 1000k -threads 4 \
-f webm "$file" &&
echo "saved as $file"
}
OPTERR=0
while getopts "f:F:d:D:swh" opt; do
case "$opt" in
f) file="$OPTARG"; overwrite=false ;;
F) file="$OPTARG"; overwrite=true ;;
w) window=true; region=false ;;
s) window=false; region=true ;;
v) verbose=true ;;
d) duration="$OPTARG" ;;
D) delay="$OPTARG" ;;
h) usage; exit 0 ;;
esac
done
[[ -z "$DISPLAY" ]] && die 'could not grab DISPLAY'
if [[ -f "$file" && "$overwrite" == false ]] && ! ask "overwrite ${file}? "; then
die
fi
getdimensions
case "$file" in
*gif)
has byzanz-record || die 'need byzanz-record for recording gifs'
delay
record-byzanz ;;
*webm)
has ffmpeg || die 'need ffmpeg for recording webms'
delay
record-ffmpeg ;;
*) die 'unknown file type, must be gif or webm' ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment