Take screenshots in background silently for archive purposes

During my work, I often try out tools of different complexity and develop usage and integration scenarios.

I use Ubuntu 18.04 LTS.

Sometimes if things get really complicated, I am not always sure how exactly I got to the solution, and for documentation and knowledge sharing purposes I spend additional time to become more aware of a neat and clean way with less messing around, take screenshots and so on.

Then I thought it would be great to have a screen capturing tool to take a picture say every 30 seconds silently in background so that I can:

  • Easily recap my steps and also gotchas
  • If I am lucky, directly use screenshots from this image archive for the documentation.

I thought I would, for example, configure a cronjob for shutter, but while I am already using it, there is an error "you have already shutter instance running". I will try now with scrot.

Any better ideas?

UPDATE: For the Cron managed execution, as this tool can't resolve time intervals less than one minute, here a solution (on of less rated answers in the thread) for every 30 seconds.

* * * * * /bin/bash -l -c "/path/to/executable; sleep 30 ; /path/to/executable"

Solution 1:

I have just started learning Ubuntu.
I don't know this method is proper or not.
I Could achieve it in the below way.

I have created a script like this named ScreenShot.sh in the folder /usr/local/bin

#!/bin/bash

# NAME: ScreenShot.sh
# PATH: /usr/local/bin
# DESC: Take Screenshots at every specified intervals with "watch -n 10 ScreenShot.sh" Command
# DATE: Oct 12th 2018

sudo gnome-screenshot -d 0

sudo chmod a+x /usr/local/bin/ScreenShot.sh

when i start the system and wanted to start the screen capture at every 10secs,

i run this command

sudo watch -n 10 ScreenShot.sh

i have configured my default folder, image type to be saved, with dconf editor in gnome-screenshot section.

enter image description here

enter image description here

enter image description here

Sounds are stopped by dconf settings under sound section

enter image description here

Solution 2:

I do the same thing. This is the script that I wrote, called screenlog-capture:

#! /bin/bash
window_name() {
  xwininfo -id "$1" | \
    grep "^xwininfo: Window id" | \
    LC_CTYPE=C LC_COLLATE=C sed  's/^[^"]*"\(.*\)"$/\1/' | \
    sanitize-filename
}

window_class() {
  xprop -id "$1" | grep "^WM_CLASS(STRING)" | cut -d '"' -f 4
  # Or we could use _NET_WM_PID(CARDINAL) -> process name
}

if [ ! -d "$RAMTMP" ]
then
  echo "RAMTMP needs to be set."
  exit 1
fi
if [ ! -e /usr/bin/puzzle-diff ]
then
    echo 'Error: puzzle-diff not installed!'
    exit 1
fi

rootdir="$HOME/screenlog"
if [ ! -w "$rootdir" ]
then
  echo 'Error: screenlog dir not writable'
  exit 1
fi
if [[ $(qdbus org.cinnamon.ScreenSaver /org/cinnamon/ScreenSaver org.cinnamon.ScreenSaver.GetActive) == true ]]
then
  exit
fi
du=$(df -Plh "$rootdir" | sed -n -e '2s/.* \([0-9]\+\)% .*/\1/' -e '2p')
if [ "$du" -ge 98 ]
then
  exit
fi
win_id=$(xprop -root | grep "^_NET_ACTIVE_WINDOW(WINDOW)" | cut -d ' ' -f 5)
win_name=$(window_name "$win_id")
parent_id=$(xprop -id "$win_id" | grep "^WM_TRANSIENT_FOR(WINDOW)" | cut -d ' ' -f 5)
if [ "$parent_id" ]
then
  win_class=$(window_class "$parent_id")
else
  win_class=$(window_class "$win_id")
fi
case "$win_class" in
  # Firefox-bin is full-screen YouTube video (for example)
  Gq|Geeqie|GQview|Firefox-bin|Plugin-container|Gimp|mplayer2)
    exit
    ;;
esac
case "$win_name" in
  *'Internet Bank'*|*'YouTube'*|MPlayer|Netflix*|Prime\ Video*)
    exit
    ;;
esac

tmpfilename="$RAMTMP/screenlog-capture.png"
scrot -buq 0 "$tmpfilename"
if [ ! -s "$tmpfilename" ]
then
  exit
fi
if [ $(stat -c %s "$tmpfilename") -lt 500000 ]
then
  mogrify -depth 3 "$tmpfilename"
else
  mogrify -type Grayscale -depth 3 "$tmpfilename"
fi
latest="$rootdir/latest.png"
puzzle-diff -c -e -E 0.1 "$latest" "$tmpfilename" &>/dev/null
if [ $? -eq 10 ]
then
  # No relevant changes, don't keep screenshot
  rm "$tmpfilename"
else
  win_name="$(printf %.30s $win_class) - $(printf %.60s $win_name)"
  date=$(date '+%Y-%m/%Y-%m-%d')
  dirname="$rootdir/$date"
  mkdir -p "$dirname"
  filename="$dirname/$(date '+%H.%M.%S') $win_name.png"
  mv "$tmpfilename" "$filename"
  rm -f "$latest"
  ln -s "$filename" "$latest"
fi

Some of the interesting features:

  • It uses scrot to take screenshots.
  • It includes the name of the current window in the filename, making lookup easier.
  • It does not run if the screensaver is running (this is Cinnamon-specific, other desktops will need a different command to check for the screensaver state).
  • It filters out some applications I don't want to take screenshots of, this list can be easily extended.
  • It stops taking screenshots if disk usage goes above 98%.
  • It uses puzzle-diff to skip saving a screenshot if it would be the same as the previous one (with some tolerance).
  • It radically reduces the color depth of the screenshots (or even makes them grayscale, depending on the size) to save disk space.
  • I use a RAM disk for intermediate storage (before deciding whether to keep an image), but you can use the regular /tmp location as well.

I use another shell script, screenlog, to call this one periodically:

#! /bin/bash
while true
do
  sleep 5
  screenlog-capture
done