Sunday, June 3, 2012

Grabbing continuous stream from IP cam

I own two Linksys WVC54GCA IP cameras. Recently, I had a need to capture a continuous stream instead of the motion activated mode where I ended up with hundreds of mp4 on my ftp server. So after looking around I found out that you can capture http stream using mplayer. So I wrote a bash script to do it.
 #!/bin/bash
#
# Duck-Wrath
# 31st May 2012
#

CHK_INT=20      # in seconds
VID_LEN=3600    # in seconds
LOGFILE=linksys_capture.log

if [ -z "$username" ]; then
   read -p "Enter Username: " username
fi

if [ -z "$password" ]; then
   read -s -p "Enter Password: " password
   printf "\n"
fi

if [ -z "$CAM_IP" ]; then
   read -p "Enter Camera IP: " CAM_IP
fi

# Linksys http URL for asf (MJPEG)
#CAM_URL=http://${CAM_IP}/img/video.mjpeg
# Linksys http URL for asf (MPEG4)
CAM_URL=http://${CAM_IP}/img/video.asf

echo "Grabbing video from ${CAM_URL}..." >> ${LOGFILE}

while [ 1 ]; do
    ASFFILE=`date +%Y%m%d-%H%M%S`.asf
    start=`date +%s`
    timer=0
    echo "Starting mplayer to grab stream." >> ${LOGFILE}
    mplayer -quiet -cache 32768 -dumpstream -dumpfile "${ASFFILE}" \
        -demuxer lavf "${CAM_URL}" \
        -user "${username}" -passwd "${password}" &
    MPID=$!
    echo "  Mplayer running on pid $MPID." >> ${LOGFILE}
    echo "  Saving to ${ASFFILE}" >> ${LOGFILE}
    while [ $timer -lt $VID_LEN ]; do
        if kill -0 $MPID; then
            now=`date +%s`
            sleep ${CHK_INT};
            timer=`echo "$now - $start" | bc`
        else
            echo "  *** Stream died prematurely." >> ${LOGFILE}
            echo "  *** Timer=${timer}." >> ${LOGFILE}
            timer=$VID_LEN
        fi
    done
    if kill -0 $MPID; then
        echo "  Terminating mplayer." >> ${LOGFILE}
        kill $MPID
    fi
    MP4FILE=`basename "${ASFFILE}" .asf`.mp4
    echo "Converting video to seekable ${MP4FILE}." >> ${LOGFILE}
    ffmpeg -i "${ASFFILE}" -f mp4 -vcodec copy -acodec copy "${MP4FILE}" && \
        /bin/rm "${ASFFILE}" && \
        echo "Captured file ${MP4FILE} Done." >> ${LOGFILE} &
    # start next capture
done
This scripts will prompt for username and password for the camera along with the IP. It then starts up mplayer to grab the stream and put in into background. The script then monitors the mplayer and updates a counter. Every hour (3600 seconds) it stop the stream captures and repackage the asf video into mp4. It then restarts capturing the next hour stream segment. If you remove the debugging log file generation, the script is relatively short.