Some things are to be configured in ipcam2rec.sh. Adjust the paths to your logfiles (if needed) and your dyndns hostname, ipcam username and password.
LOGFILE="/var/log/ipcam.log" FTPLOGFILE="/var/log/proftpd/proftpd.log" CAMHOST="http://stream:pass@mynick.dyndns.org"
And here are the names and the ports (you forwarded the cams to) of every single cam. You can add up to 10 cams.
if [[ $cam =~ 'ipcam1' ]]; then cam='ipcam1'; port=1111; fi if [[ $cam =~ 'ipcam2' ]]; then cam='ipcam2'; port=1112; fi if [[ $cam =~ 'ipcam3' ]]; then cam='ipcam3'; port=1113; fi
Installing the script is easy done. There are two cronjobs to install. The first one runs each minute and looks for cam to switch off (in case the last “FTP ping” is older than 1 minute). The second jobs also runs each minute and starts the ipcam2rec daemon if that is not started yet. (I’m sure, it can be done better with some rc.d stuff, but I’m not familiar with it.) So just add these lines to your cron table:
* * * * * find /var/run/ipcam?.pid -mmin +1 -exec /path/to/ipcam2rec.sh stopcam {} \; 1>/dev/null 2>&1 * * * * * if [ "`pidof -sx ipcam2rec.sh`" = "" ]; then nohup /path/to/ipcam2rec.sh start 1>/dev/null 2>&1 & fi
Starting the script is not needed, it will be started automatically by the cronjob within a minute. You can look how the daemon works in the logfile:
tail -f /var/log/ipcam.log
You may also want to setup a logrotation job in /etc/logrotate.d/ipcam for the log file:
/var/log/ipcam.log { weekly missingok rotate 4 compress notifempty sharedscripts }
And you have to add this line to the postrotate section for /var/log/proftpd/proftpd.log in /etc/logrotate.d/proftpd-basic in order to restart the daemon after log rotation. Otherwise inotifywait seems to loose the logfile monitoring after log rotation.
/path/to/ipcam2rec.sh stop # Restarts automatically by cron
And this is how the process tree is looking like:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 29498 0.0 0.2 16884 1420 ? S 21:37 0:00 /bin/sh ipcam2rec.sh start root 29500 0.0 0.1 6028 572 ? S 21:37 0:00 _ inotifywait ... root 29501 0.0 0.1 16908 1032 ? S 21:37 0:00 _ /bin/sh /root/ipcam2rec.sh start root 29528 15.6 15.5 144852 81604 ? S 21:37 0:06 _ /usr/local/bin/ffmpeg ... root 29560 7.5 15.6 144864 81988 ? S 21:37 0:02 _ /usr/local/bin/ffmpeg ...
As you see Ffmpeg processes takes a lot of RAM (15% each on my VPS). Thatswhy many parallel records can slow down your server. CPU load is not that problematic because the total load depends on the image frames transmitted per second and this amount is restricted by the upload bandwidth.
Daily job for finalizing video and cleaning up is also done by the main ipcam2rec.sh script. You may want to adjust the FTP directories or the path for the resulting files in the finalize section. Then just add this line to your cron table in order to start finalizing each night at 0:00 pm.
0 0 * * * /path/to/ipcam2rec.sh finalize YESTERDAY
The script does two things:
- Process the single images uploaded by the cam via FTP into mp4 file. It adds a timestamp to each image using mogrify and then encode the images with Ffmpeg. The images will be deleted after that if you add clean to the command.
- Check and merge the mp4 files recorded by the daemon during the day using AtomicParsley and MP4Box. The single mp4 files are deleted then if you add clean to the command. The limitation of MP4Box is that it only allows to merge 20 mp4 files at time. So we need a script called mergeMP4.sh for merging even more files.
#!/bin/bash ################################################################## # mergeMP4.sh # Merges multiple mp4 files # # USAGE: mergeMP4.sh -i "file1 file2" # # OUTPUT: final.mp4 (override this with -o new_target_name.mp4) # ################################################################## DIRS="." OFILE="" TARGET="final.mp4" while getopts "i:o:a" opt; do case $opt in i) DIRS=$OPTARG ;; o) TARGET=$OPTARG ;; *) echo "USAGE: $0 -i file_list [-o output_file]" exit 1 ;; esac done MP4BOX_PARAMS="" MP4BOX_OPT="" first=0 scale=4 page_size=10 listing=$DIRS # convert to an array for easy access count=1 for item in $listing; do array_listing[$count]=$item count=$((count + 1)) done page_size=10 total_files=`echo $listing | wc -w` page=1; pages=$(($total_files / page_size)) last_items=$(($total_files % page_size)) # Work on the array index=1 while [ $page -le $pages ]; do count=1 mp4box_args="" while [ $count -le $page_size ]; do if [ "$mp4box_args" == "" ]; then mp4box_args="-add ${array_listing[$index]}" else mp4box_args="$mp4box_args -cat ${array_listing[$index]}" fi count=$((count + 1)) index=$((index + 1)) done printf -v OFILE "ofile_%03d.mp4" $page /usr/bin/MP4Box $MP4BOX_PARAMS $mp4box_args -new $OFILE page=$((page + 1)) done if [ $last_items -gt 0 ]; then count=1 printf -v OFILE "ofile_%03d.mp4" $page mp4box_args="" while [ $count -le $last_items ]; do if [ "$mp4box_args" == "" ]; then mp4box_args="-add ${array_listing[$index]}" else mp4box_args="$mp4box_args -cat ${array_listing[$index]}" fi count=$((count + 1)) index=$((index + 1)) done /usr/bin/MP4Box $MP4BOX_PARAMS $mp4box_args -new $OFILE fi mp4box_args="" for ofile in `ls ofile*`; do if [ "$mp4box_args" == "" ]; then mp4box_args="-add $ofile" else mp4box_args="$mp4box_args -cat $ofile" fi done /usr/bin/MP4Box $MP4BOX_PARAMS $mp4box_args -new $TARGET rm ofile*.mp4 exit 0
Now you know how it’s done.