Laurent22 on Github has developed a very simple bash script for capturing images using a standard default webcam with motion detection support attached to your system. This bash script process was developed to assist Laurent22 to record what his dog was doing while he wasn't at home.
The daily driver used by Laurent 22 is OSX. However, the bash script that he developed for creating images that can be converted into a motion picture .mp4 file for viewing using VLC Media Player, is cross-platform and can be run in Linux and MS Windows as well.
Frames are captured at regular intervals using ffmpeg. Next, ImageMagick's compare tool is used to check if a frame is similar to its predecessor frame. If these two frames are substantively different, then they are preserved, otherwise they are discarded in order ro conserve hard drive space. This process provides a very simple motion detection methodology and avoids filling up the hard drive with duplicate frames.
Installation
OSX
brew install ffmpeg
brew install imagemagick
curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh
Linux (Debian)
sudo apt-get install ffmpeg
# or: sudo apt-get install libav-tools
sudo apt-get install imagemagick
curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh
Windows
(Not tested)
- Install [Cygwin](https://www.cygwin.com/) or [MinGW](http://www.mingw.org/)
- Install [ffmpeg](http://ffmpeg.zeranoe.com/builds/)
- Install [ImageMagick](http://www.imagemagick.org/script/binary-releases.php)
Usage
./pmcam.sh
The contents of the pmcam.sh file is as follows:
#!/usr/bin/env bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
OUTPUT_DIR="$SCRIPT_DIR/images"
CAPTURE_INTERVAL="1" # in seconds
FFMPEG=ffmpeg
command -v $FFMPEG >/dev/null 2>&1 || { FFMPEG=avconv ; }
DIFF_RESULT_FILE=$OUTPUT_DIR/diff_results.txt
fn_cleanup() {
rm -f diff.png $DIFF_RESULT_FILE
}
fn_terminate_script() {
fn_cleanup
echo "SIGINT caught."
exit 0
}
trap 'fn_terminate_script' SIGINT
mkdir -p $OUTPUT_DIR
PREVIOUS_FILENAME=""
while true ; do
FILENAME="$OUTPUT_DIR/$(date +"%Y%m%dT%H%M%S").jpg"
echo "-----------------------------------------"
echo "Capturing $FILENAME"
if [[ "$OSTYPE" == "linux-gnu" ]]; then
$FFMPEG -loglevel fatal -f video4linux2 -i /dev/video0 -r 1 -t 0.0001 $FILENAME
elif [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OSX
$FFMPEG -loglevel fatal -f avfoundation -i "default" -r 1 -t 0.0001 $FILENAME
fi
if [[ "$PREVIOUS_FILENAME" != "" ]]; then
# For some reason, `compare` outputs the result to stderr so
# it's not possibly to directly get the result. It needs to be
# redirected to a temp file first.
compare -fuzz 20% -metric ae $PREVIOUS_FILENAME $FILENAME diff.png 2> $DIFF_RESULT_FILE
DIFF="$(cat $DIFF_RESULT_FILE)"
fn_cleanup
if [ "$DIFF" -lt 20 ]; then
echo "Same as previous image: delete (Diff = $DIFF)"
rm -f $FILENAME
else
echo "Different image: keep (Diff = $DIFF)"
PREVIOUS_FILENAME="$FILENAME"
fi
else
PREVIOUS_FILENAME="$FILENAME"
fi
sleep $CAPTURE_INTERVAL
done
This script should be made executable using the command:
chmod +x pmcam.sh
and then executed using the command:
./pmcam.sh
This bash script will use your default webcam to capture frames. To capture using a different camera other than the default detected, the ffmpeg command `-i` parameter can be changed - see the [ffmpeg documentation](https://trac.ffmpeg.org/wiki/Capture/Webcam) for more information.
A frame will then be saved approximately once every second to the "images" folder in the same directory as the Bash script. Both delay and target folder can be changed in the script.
To stop the script, press Ctrl + C.
This bash script process is covered under the MIT license.
Concatenating Multiple Image Files to an MP4 Video Format
Once the images are captured using the bash script process delineated previously, you can easily concatenate these images into a .mp4 format that produces a raw video from those images.
To accomplish this, go into your *Images* folder, locate the individual image files, then run the concatenation command to concatenate these image files into one single .mp4 file. So, if you have the following image files in the *images* folder, the command to run in the terminal would be:
$ cat imageFile1 imageFile2 ... imageFileN > movie.mp4
which concatenates imageFile1, imageFile2, through imageFileN into one file called movie in the .mp4 format since we used the .mp4 extension on the final file.