Create images from Webcam images

It is just a pain in the ass if you cannot get any work done because you have to constantly check if the image of a webcam has changed. Therefore I wrote a shell script that downloads the webcam images and puts them together as a video.

What the scrip does is the following:

  1. download an image from an url
  2. check if the image is the same as the last one (do not store duplicates)
  3. Create a video from all downloaded images

Now let’s give some credit where it is due:
Downloading the image can be done with either wget or curl. However the file must be renamed do avoid overriding: Curl for grabbing webcam pics in succession?
Basically there are three ways to create a movie from images. Two are described in Making movies from image files using ffmpeg/mencoder. The third did not work for me but this may because I use Ubuntu Gnome. On a KDE desktop it might work. This solution however only works with a desktop an cannot be run on a server or a NAS.
The iterative aspect of the execution of the script I solved with a cron job.

I put the code into two functions. The first takes for arguments:

  1. The URL from where to download the image
  2. The path where the image is to be stored
  3. The name of the video file (without file extension)
  4. The file name of the downloaded image
downloadAndCreateMovie(){
	STORE_PATH=$2
	URL=$1

	if [ ! -d $STORE_PATH ]
	then
		mkdir $STORE_PATH
	fi
	cd $STORE_PATH
	PREFIX=$3
	LASTFILE=`ls -Atr *.jpg | tail -1`
	FILENAME=$4


#	curl -O $URL
	wget -q $URL

	MD5LAST=`md5sum -b $LASTFILE | sed 's: :\n:g' | head -1`

	MD5CUR=`md5sum -b  $FILENAME | sed 's: :\n:g' | head -1`

	if test $MD5LAST != $MD5CUR
	then
		cp -v $FILENAME `date +"%y%m%d-%H%M%S"`.jpg
		images2movie $PREFIX
	fi
	rm $FILENAME
}

First we make sure that the directory where we store the images exists. Then we figure out what the file name of the latest downloaded image is. We can then download the image with curl or wget. To compare the two files (the latest and the just downloaded) we compute the md5 checksum and compare them. If the do not match we rename the downloaded file by giving it a timestamp as a file name and then call the second function to create the video.
This function has some drawbacks:

  1. The name of the downloaded image could be retrieved from the URL
  2. If the function is called upon an empty folder there is no last file and the function gets stuck in the computation of the md5 sum of “
  3. There is no exception handling on the download. I guess it will just time out the there will be no image

Now the second function creates the video from the image files. It takes the name of the video file as an argument. I choose the ffmpeg approach since it did work better for me and might work better on a NAS.

images2movie(){
	MOVIE_NAME="movie"
	MOVIE_NAME=$1
	DURATION=3
	mkdir movie
	FILECOUNTER=`printf "%05d" 0`
	for file in `ls`
	do
		for ((  i = 0 ;  i < = $DURATION;  i++  ))
		do
			cp $file movie/$FILECOUNTER.jpg
			FILECOUNTER=`expr $FILECOUNTER + 1`
			FILECOUNTER=`printf "%05d" $FILECOUNTER`	
		done
	done
	rm $MOVIE_NAME.mp4
	ffmpeg -r 1 -b 1800  -s svga -i movie/%05d.jpg $MOVIE_NAME.mp4
	rm -rf movie
}

The video is created with a frame rate of one frame per second. If you want to display the same image over several seconds you have to input it several times. The variable DURATION defines how many times. The images are copied into the temporary video directory. The file name is changed to consecutive numbering with five digits starting with 0. The tricky part is the counting: The file name is a string so you have to evaluate the expression of adding 1 to the numeric file name and then reformatting it as a five digit string.
The next thing is to create the video from the sample images. The parameter -r specifies the frames per second. The parameter -b defines the bitrate. The parameter -s defines the output format. Here you will want to select a format that matches the format of the images for best quality. The parameter -i defines the input using the same expression as the file name. The last parameter is the output file name.
Basically that's it. Therefore the call would look like this:

STORE_PATH=~/Pictures/kronplatz/Marchner
URL=http://www.kronplatz.com/_webcam/70/webcam7.jpg
downloadAndCreateMovie $URL $STORE_PATH Marchner webcam7.jpg

To install this a a cronjob issue

crontab -e

on the console and add this line

*/10 *    * * * /home/andi/bin/downloadImage.sh > /dev/null 2>&1

You will want to apply the correct path to your script. This line executes the script every ten minutes and throws away all output. If the images on the URL are replaced regularly you are doing good in choosing the same interval here.
When closing the editor the temporary file will be stored and installed as cron job.

The script can be downloaded:
downloadImage.sh

3 Gedanken zu „Create images from Webcam images“

  1. It might be necessary to add the path variable in the crontab. PATH=$PATH:$HOME/bin does not work, you will want to specify the full path.
    If you have further problems you can redirect the log output to a file by replacing /dev/null with the path to the file.

  2. Using ffmpeg as shown produces some block artefacts. I found an alternative in dvd-slideshow which can be installed with sudo apt-get install dvd-slideshow.
    Then replace the ffmpeg line with the following:

    dvd-slideshow -n $MOVIE_NAME -o . -f $SLIDESHOW

    $SLIDESHOW holds the filename of the input file that you have to generate in the for loop where you iterate over all *.jpg files in the directory:

    echo $file':1' >> $SLIDESHOW

    This will generate a *vob file of considerable size. You can add the -flv flag to reduce the size by factor 10 but this will introduce some block artefacts again.

Schreibe einen Kommentar