├── .gitignore ├── pmcam.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | images/ 3 | -------------------------------------------------------------------------------- /pmcam.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | OUTPUT_DIR="$SCRIPT_DIR/images" 5 | 6 | CAPTURE_INTERVAL="1" # in seconds 7 | FFMPEG=ffmpeg 8 | command -v $FFMPEG >/dev/null 2>&1 || { FFMPEG=avconv ; } 9 | DIFF_RESULT_FILE=$OUTPUT_DIR/diff_results.txt 10 | 11 | fn_cleanup() { 12 | rm -f diff.png $DIFF_RESULT_FILE 13 | } 14 | 15 | fn_terminate_script() { 16 | fn_cleanup 17 | echo "SIGINT caught." 18 | exit 0 19 | } 20 | trap 'fn_terminate_script' SIGINT 21 | 22 | mkdir -p $OUTPUT_DIR 23 | PREVIOUS_FILENAME="" 24 | while true ; do 25 | FILENAME="$OUTPUT_DIR/$(date +"%Y%m%dT%H%M%S").jpg" 26 | echo "-----------------------------------------" 27 | echo "Capturing $FILENAME" 28 | if [[ "$OSTYPE" == "linux-gnu" ]]; then 29 | $FFMPEG -loglevel fatal -f video4linux2 -i /dev/video0 -r 1 -t 0.0001 $FILENAME 30 | elif [[ "$OSTYPE" == "darwin"* ]]; then 31 | # Mac OSX 32 | $FFMPEG -loglevel fatal -f avfoundation -i "default" -r 1 -t 0.0001 $FILENAME 33 | fi 34 | 35 | if [[ "$PREVIOUS_FILENAME" != "" ]]; then 36 | # For some reason, `compare` outputs the result to stderr so 37 | # it's not possibly to directly get the result. It needs to be 38 | # redirected to a temp file first. 39 | compare -fuzz 20% -metric ae $PREVIOUS_FILENAME $FILENAME diff.png 2> $DIFF_RESULT_FILE 40 | DIFF="$(cat $DIFF_RESULT_FILE)" 41 | fn_cleanup 42 | if [ "$DIFF" -lt 20 ]; then 43 | echo "Same as previous image: delete (Diff = $DIFF)" 44 | rm -f $FILENAME 45 | else 46 | echo "Different image: keep (Diff = $DIFF)" 47 | PREVIOUS_FILENAME="$FILENAME" 48 | fi 49 | else 50 | PREVIOUS_FILENAME="$FILENAME" 51 | fi 52 | 53 | sleep $CAPTURE_INTERVAL 54 | done 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pmcam - poor man's video capture with motion detection in Bash 2 | 3 | This simple Bash script captures images from a webcam with motion detection support. I wanted to find out what my dog was up to when I am not at home, but could not find any free video capture software on OS X. I put together this quick and dirty solution, which does the job surprisingly well. 4 | 5 | Frames are captured at regular intervals using `ffmpeg`. Then ImageMagick's `compare` tool is used to check if this frame is similar to the previous one. If the frames are different enough, they are kept, otherwise they are deleted. This provide very simple motion detection and avoids filling up the hard drive with duplicate frames. 6 | 7 | ## Installation 8 | 9 | ### OS X 10 | 11 | brew install ffmpeg 12 | brew install imagemagick 13 | curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh 14 | 15 | ### Linux (Debian) 16 | 17 | sudo apt-get install ffmpeg 18 | # or: sudo apt-get install libav-tools 19 | sudo apt-get install imagemagick 20 | curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh 21 | 22 | ### Windows 23 | 24 | (Not tested) 25 | 26 | * Install [Cygwin](https://www.cygwin.com/) or [MinGW](http://www.mingw.org/) 27 | * Install [ffmpeg](http://ffmpeg.zeranoe.com/builds/) 28 | * Install [ImageMagick](http://www.imagemagick.org/script/binary-releases.php) 29 | 30 | ## Usage 31 | 32 | ./pmcam.sh 33 | 34 | The script will use the default webcam to capture frames. To capture using a different camera, the ffmpeg command `-i` parameter can be changed - see the [ffmpeg documentation](https://trac.ffmpeg.org/wiki/Capture/Webcam) for more information. 35 | 36 | A frame will then be saved approximately every 1 second to the "images" folder next to the Bash script. Both delay and target folder can be changed in the script. 37 | 38 | To stop the script, press Ctrl + C. 39 | 40 | ## TODO 41 | 42 | * Allow specifying the video capture source and format (curently hardcoded) 43 | * Command line argument to change frame directory. 44 | * Command line argument to change interval between frame captures. 45 | * Command line argument to specify the threshold for a frame to be kept. 46 | 47 | ## License 48 | 49 | MIT 50 | --------------------------------------------------------------------------------