Here the code after your patches (hope I've applied them correctly) and the SQL correction previously mentioned:
Code: Select all
#!/bin/bash
# Original script posted here https://forums.zoneminder.com/viewtopic.php?f=9&t=27537 by russell_i_brown
# Install to /opt/zmrecord.sh
# Grab a video stream from an IP camera into a temp file.
# Inject an 'Events' record into the ZM Database.
# Create the directory in the zm storage area
# Move the mp4 to the right place
#
# Call with the Camera Id number as arg1:
#
# zmrecord.sh 12
#
#
# You might have to install mediainfo which I use to grab
# the frame count.
#
# Version 0.1 - russell_i_brown 18/ 9/18 First hack
# Version 0.2 - russell_i_brown 19/ 9/18 Read monitor guff from DB
# Version 0.3 - russell_i_brown 19/ 9/18 Set StorageId in DB
# Version 0.4 - matt_watts 10/12/19 Use FFMPEG segment output to ensure frames are not missed between segments
# Version 0.5 - matt_watts 12/12/19 Move video segments immediatley into database / storage tree while live and keep db stats updated
# Version 0.6 - matt_watts 16/12/19 - Replace FFMPEG list output with simple folder polling allowing some crash/script kill recovery
# - Use FFMPEG empty_moov flag to allow playing in-recording segment in the web ui and preventing
# corrupt video on crash/script kill
# - Continuous event database updates as segment is being wrote
# - Log some errors and events direct to Zoneminders DB Log
# Version 0.7 - russell_i_brown 31/01/20 Use Event Prefix as requested by tuxmos
# Handle Monitor with a StorageId of 0 by defaulting to 1 if blank (ZM 1.34 issue?)
# Calculate the Bandwidth so the ZM console looks sane.
#########################################
# Recording chunk time in seconds
# This script will record for this number of seconds at a time
# 600 (10 minutes) is what I use.
RECORD_TIME=600
# MySQL
# set the user this way, if needed
# (NOTE: you could pass other options here, if needed, such as -h, etc)
#MYSQL_AUTH=()
MYSQL_AUTH=(-h <MySQLHost> -u zmuser)
# set the password here, if needed
export MYSQL_PWD="SECRET_PWD"
# some checks, as this script depends upon these things
# (leaving stderr unvarnished, so end user gets more info)
if ! mediainfo --version >/dev/null; then
echo "Problem with mediainfo, maybe apt-get install mediainfo?"
exit 1
fi
if ! bc -v >/dev/null; then
echo "Problem with bc, maybe apt-get install bc?"
exit 1
fi
# 0 or 1
debug=1
#
#########################################
trap "kill 0" SIGINT
# ZM Log
function zm_log() {
CODE="$1"
CODEVAL="$2"
MESSAGE="`echo $3|tr -d '"'`"
TIMESTAMP=`date +%s`
SQL="INSERT INTO Logs ( Component,File,ServerId,Pid,Level,Code,Line,TimeKey, Message )
VALUES ( 'zmrecord.sh', 'zmrecord.sh', NULL, $$, $CODEVAL, \"$CODE\", 0, $TIMESTAMP, \"$MESSAGE\" );"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
}
function log_inf() {
zm_log "INF" "2" "$@"
}
function log_err() {
zm_log "ERR" "-2" "$@"
}
# Run the ffmpeg process and keep stats file up to date while it runs - pass ffmpeg errors to zm log
function run_ffmpeg() {
MONITOR_ID="$1"
CAM_URL="$2"
OUTPUT_STATS_FN="$3"
RECTIME="$4"
OUTPUT_FN="$5"
rm "$OUTPUT_STATS_FN".errorpipe 2>/dev/null
mkfifo "$OUTPUT_STATS_FN".errorpipe
rm "$OUTPUT_STATS_FN".statpipe 2>/dev/null
mkfifo "$OUTPUT_STATS_FN".statpipe
cat "$OUTPUT_STATS_FN".errorpipe | \
while read ERR; do
log_err "Monitor: $MONITOR_ID FFMPEG: $ERR"
done &
PID_ERR_READ=$!
cat "$OUTPUT_STATS_FN".statpipe | \
while read LN; do
PARM="`echo $LN | cut -d '=' -f1`"
VAL="`echo $LN | cut -d '=' -f2`"
if [ "$PARM" = "fps" ]; then FFMPEG_FPS=$VAL; fi
if [ "$PARM" = "bitrate" ]; then FFMPEG_BITRATE=$VAL; fi
if [ "$PARM" = "frame" ]; then FFMPEG_FRAME=$VAL; fi
echo "`date +%s` $FFMPEG_FPS $FFMPEG_BITRATE $FFMPEG_FRAME" > "$OUTPUT_STATS_FN"
done &
PID_STAT_READ=$!
ffmpeg -y -loglevel error -i "$CAM_URL" -c copy ${DOAUDIO[@]} -f segment \
-segment_time $RECTIME -segment_atclocktime 1 -segment_format_options movflags=empty_moov -strftime 1 "$OUTPUT_FN" \
-progress - -nostats 2>"$OUTPUT_STATS_FN".errorpipe 1>"$OUTPUT_STATS_FN".statpipe &
PID_FFMPEG=$!
# Wait for exit signal or child pid death
RUNNING=1
trap 'RUNNING=0' EXIT
trap 'RUNNING=0' INT
trap 'RUNNING=0' TERM
while [ "$RUNNING" = "1" ]; do
if ! kill -0 "$PID_FFMPEG" 2>/dev/null; then RUNNING=0; fi
if ! kill -0 "$PID_ERR_READ" 2>/dev/null; then RUNNING=0; fi
if ! kill -0 "$PID_STAT_READ" 2>/dev/null; then RUNNING=0; fi
sleep 1
done
# Shutdown the subprocess - we want to make really really sure that FFMPEG has indeed died before leaving!
# its not 100% perfect and the output from netcams can really freeze it occassionaly to the point SIGINT
# does not work and the subprocess exiting will leave a zombie ffmpeg behind
# if it does not shutdown in 4 seconds force kill it
kill $PID_FFMPEG $PID_ERR_READ $PID_STAT_READ 2>/dev/null
KILL_TIMEOUT=0
RUNNING=1
trap 'RUNNING=1' EXIT
trap 'RUNNING=1' INT
trap 'RUNNING=1' TERM
while [ "$RUNNING" = "1" ]; do
KILL_TIMEOUT=$((KILL_TIMEOUT+1))
if ! kill -0 "$PID_FFMPEG" 2>/dev/null; then RUNNING=0; fi
if [ "$KILL_TIMEOUT" -gt 4 ]; then
kill -9 $PID_FFMPEG 2>/dev/null
fi
sleep 1
done
rm "$OUTPUT_STATS_FN".errorpipe 2>/dev/null
rm "$OUTPUT_STATS_FN".statpipe 2>/dev/null
log_err Monitor: $MONITOR_ID FFMPEG Has Terminated
}
# Scan the tmp folder for <timestamp>.mp4 files
# Move them into the correct tree and create a DB entry ensuring that on premature script termination what data was
# captured so far is in place
# leave an eventid and symbolic link in the tmp folder
# the eventid keeps the info for this script to poll the video in its new location
# the symbolic link allows ffmpeg to re-open the file. FFMPEG does this when quit earlier than expected to add the moov atom (faststart)
function addIncompleteVideosToDB() {
TMPFOLDER="$1"
MONITOR_ID="$2"
STORAGEID="$3"
RECORD_TIME="$4"
WIDTH="$5"
HEIGHT="$6"
STORE_PATH="$7"
EVENT_PREFIX="$8"
# iterate all new mp4 files found
for FILEPATH in "$TMPFOLDER"/*.mp4; do
[ -f "$FILEPATH" ] || continue
# get beginning timestamp from ffmpeg created filename
FILENAME=${FILEPATH##*/}
TIMESTAMP=${FILENAME%%.mp4}
# create new db entry for video segment
SQL=" INSERT INTO Events
( MonitorId,StorageId,Name,Cause,StartDateTime,EndDateTime,Width,Height,Length,Frames,
Videoed,DiskSpace,Scheme,StateId,AlarmFrames,SaveJPEGs,Notes)
VALUES
( $MONITOR_ID,\"$STORAGEID\",\"New Event\",\"Continuous\",FROM_UNIXTIME($TIMESTAMP),
NULL,$WIDTH,$HEIGHT,1,1,1,1,\"Medium\",1,0,0,\"manual ffmpeg\");
SET @last_id = LAST_INSERT_ID();
INSERT into Frames set EventId=@last_id,FrameId=1,Type=\"Normal\",TimeStamp=FROM_UNIXTIME($TIMESTAMP),Delta=0.00,Score=0;
UPDATE Events SET DefaultVideo=CONCAT(@last_id,\"-video.mp4\") where Id=@last_id;
SELECT @last_id;"
THIS_ID=`echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm`
# if mysql returned a new eventid then move the video into the correct place
# ffmpeg will still retain its handle to the file and continue writing
# leave an eventid reference to the video in the tmp folder - this will allow
# polling of the file until it needs completing
if ! [ "$THIS_ID" -le 0 ]; then
DATE_PATH=$STORE_PATH/`date -d @$TIMESTAMP --rfc-3339=date`
THIS_PATH=$DATE_PATH/$THIS_ID
NEW_VIDEO_PATH="$THIS_PATH"/$THIS_ID-video.mp4
DESCFILE="$TMPFOLDER"/"$TIMESTAMP".eventid
mkdir -p $THIS_PATH
mv -f "$FILEPATH" "$NEW_VIDEO_PATH"
chown www-data:www-data "$NEW_VIDEO_PATH" "$THIS_PATH" "$DATE_PATH"
echo "$THIS_PATH/$THIS_ID-video.mp4" > "$DESCFILE"
log_inf "Monitor: $MONITOR_ID - New segment : $THIS_PATH/$THIS_ID-video.mp4 Event $THIS_ID"
fi
done
}
# Scan the tmp folder for <timestamp>.eventid files
# By checking which ones point to an mp4 that is not open ( by ffmpeg ) we can determine
# the segment is complete and close it. This can also pick up stray recordings after say a PC crash
function addCompleteVideosToDB() {
TMPFOLDER="$1"
MONITOR_ID="$2"
STORAGEID="$3"
RECORD_TIME="$4"
WIDTH="$5"
HEIGHT="$6"
STORE_PATH="$7"
# iterate all eventid files in the tmp folder
for EVENTID_FILEPATH in "$TMPFOLDER"/*.eventid; do
[ -f "$EVENTID_FILEPATH" ] || continue
EVENTID_FILENAME=${EVENTID_FILEPATH##*/}
TIMESTAMP=${EVENTID_FILENAME%%.eventid}
[[ $TIMESTAMP =~ ^[0-9]+$ ]] || continue
VIDEO_PATH="`cat "$EVENTID_FILEPATH"`"
VIDEO_FILENAME=${VIDEO_PATH##*/}
EVENTID=${VIDEO_FILENAME%%-video.mp4}
# if the video is not longer open for writing remove the eventid file, this will be the last update
LASTUPDATE=0
if [ "`fuser "$VIDEO_PATH" 2>/dev/null`" = "" ]; then
log_inf "Monitor: $MONITOR_ID Event : $EVENTID - Segment complete : $VIDEO_PATH"
rm "$EVENTID_FILEPATH"
LASTUPDATE=1
# as this is the last run, change the name
SQL="UPDATE Events SET Name=\"${EVENT_PREFIX}${EVENTID}\" where Id=$EVENTID;"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
fi
# get video stats and validate them
# only spit out actual errors if this is the final update (video finished), an in-writing video
# is likley to not be stat ready early in its life
FRAMES=`mediainfo --Output="Video;%FrameCount%" "$VIDEO_PATH"`
if ! [[ $FRAMES =~ ^[0-9]+$ ]]; then
if [ $LASTUPDATE -eq 1 ]; then
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: mediainfo --Output=Video;%FrameCount% $VIDEO_PATH returned '$FRAMES', probable corrupt video"
fi
FRAMES=1
fi
FILESIZE=`stat -c%s "$VIDEO_PATH"`
if ! [[ $FILESIZE =~ ^[0-9]+$ ]]; then
if [ $LASTUPDATE -eq 1 ]; then
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: stat -c%s $VIDEO_PATH returned '$FILESIZE', integer expecected"
fi
FILESIZE=1
fi
END_TIMESTAMP=`stat -c %Y "$VIDEO_PATH"`
if ! [[ $END_TIMESTAMP =~ ^[0-9]+$ ]]; then
if [ $LASTUPDATE -eq 1 ]; then
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: stat -c %Y $VIDEO_PATH returned '$END_TIMESTAMP', integer expecected"
fi
LENGTH=$RECORD_TIME
END_TIMESTAMP=$((TIMESTAMP+1))
fi
# update the db with stats
SQL=" UPDATE Events SET
Frames=$FRAMES,
EndDateTime=FROM_UNIXTIME($END_TIMESTAMP),
DiskSpace=$FILESIZE
WHERE Id=$EVENTID;
UPDATE Events SET Length=UNIX_TIMESTAMP(EndDateTime)-UNIX_TIMESTAMP(StartDateTime)
WHERE StartDateTime IS NOT NULL AND EndDateTime IS NOT NULL AND Id=$EVENTID;"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
if [ $LASTUPDATE -eq 1 ]; then
if [ $FRAMES -gt 1 ]; then
LENGTH=$(echo "scale=0;$(mediainfo --Output="Video;%Duration%" "$VIDEO_PATH") / 1000" | bc)
STARTTIME=$((END_TIMESTAMP - $LENGTH))
# if we see a linked_monitor_id, then try to detect alarm frames there
if [[ $LINKED_MONITOR_ID =~ ^[0-9]+$ ]]; then
SQL="SELECT count(*) from Events where MonitorId=$LINKED_MONITOR_ID and AlarmFrames > 0 and StartDateTime > FROM_UNIXTIME($STARTTIME) and EndDateTime < FROM_UNIXTIME($END_TIMESTAMP);"
#
ALARMFRAMES=$(echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm)
if [[ $ALARMFRAMES =~ ^[0-9]+$ ]] && [ $ALARMFRAMES -gt 0 ]; then
SQL="UPDATE Events set AlarmFrames=$ALARMFRAMES where id=$EVENTID"
echo "FOUND ALARM: $SQL"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
fi
fi
#
# calc number of bulk frames, and single frames
BULKNUMBER=100
FRAMERATE=$(mediainfo --Output="Video;%FrameRate%" "$VIDEO_PATH")
if ! [[ $FRAMERATE =~ ^[0-9.]+$ ]]; then
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: mediainfo FrameRate check on "$VIDEO_PATH" returned '$FRAMERATE', integer expecected"
return
fi
skew=$(echo "scale=2; 1 / ${FRAMERATE}" | bc)
skewbulk=$(echo "scale=2; $BULKNUMBER / ${FRAMERATE}" | bc)
# we could leave out the 00 + bulk divide, but it may not be 100!
COUNTINGIT=$(echo "scale=2; ${FRAMES}/${BULKNUMBER}" | bc)
bulkcount=${COUNTINGIT:0:-3}
# bc hates 0 pre-decimal
if [ "$bulkcount" == "" ]; then
bulkcount=0
fi
# get remainder, plus force base 10 to strip and leading 0s.
# (prevents interpretation as octal, etc)
framecount=$((10#${COUNTINGIT: -2}))
if [ $debug -eq 1 ]; then
echo "COUNTINGIT=$COUNTINGIT bc=$bulkcount fc=$framecount FRAMES=$FRAMES FRAMERATE=$FRAMERATE skew=$skew skewbulk=$skewbulk"
fi
# these need to be sensible numbers
if [[ $bulkcount =~ ^[0-9]+$ ]] && [[ $framecount =~ ^[0-9]+$ ]] && [[ $skew =~ ^\.[0-9]+$ ]] && [[ $skewbulk =~ ^[0-9]+\.[0-9]+$ ]] && [[ $EVENTID =~ ^[0-9]+$ ]] && [[ $STARTTIME =~ ^[0-9]+$ ]]; then
# clear out temp single frame
SQL="delete from Frames where EventId='$EVENTID';"
if [ $bulkcount -gt 0 ]; then
for (( i=0;i<=$bulkcount;i++)); do
currentskew=$(echo "scale=2; $skewbulk * $i" | bc)
if [ $i -gt 0 ]; then
currentbulk=$(echo "scale=0; ${BULKNUMBER} * $i" | bc)
else
currentbulk=1
fi
frametime=$(echo "scale=0; ${STARTTIME} + ${currentskew} / 1" | bc)
SQL+=$'\n'"INSERT into Frames (EventId,FrameId,Type,TimeStamp,Delta) values ('$EVENTID','$currentbulk','Bulk',FROM_UNIXTIME($frametime),'$currentskew');"
done
fi
# get current skew/bulk as a base
existingskew=$(echo "scale=2; $skewbulk * $bulkcount" | bc)
existingbulk=$(echo "scale=0; ${BULKNUMBER} * $bulkcount" | bc)
for (( i=1;i<=$framecount;i++)); do
currentskew=$(echo "scale=2; $skew * $i + $existingskew" | bc)
frametime=$(echo "scale=0; ${STARTTIME} + ${currentskew} / 1" | bc)
currentframe=$(echo "scale=0; $i + $existingbulk " | bc)
SQL+=$'\n'"INSERT into Frames (EventId,FrameId,Type,TimeStamp,Delta) values ('$EVENTID','$currentframe','Normal',FROM_UNIXTIME($frametime),'$currentskew');"
done
if [ $debug -eq 1 ]; then
echo "Writing SQL for EventId=$EVENTID"
echo "$SQL"
fi
#echo "$SQL"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
else
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: Value(s) bulkcount=$bulkcount framecount=$framecount skew=$skew skewbulk=$skewbulk not valid. Cannot update Frame table."
fi
else
log_err "Monitor: $MONITOR_ID Event : $EVENTID ERROR: Frame rate too low, unable to accurate add frame data."
fi
fi
done
}
# For Bandwidth Calc
LAST_FPS_TIME=0
LAST_FILESIZE=0
LAST_BW=0
# Keep the monitor status up to date so fps etc can be viewed in the zm console
function updateMonitorStatus() {
MONITOR_ID="$1"
STATS_FILE="$2"
SHUTTINGDOWN="$3"
STATUS="NotRunning"
FPS=0
BW=0
if ! [ "$SHUTTINGDOWN" = "1" ]; then
if [ -f "$STATS_FILE" ]; then
IFS=' ' read -r TS FPS BW FRAME <<< `cat "$STATS_FILE"`
if [ $debug -eq 1 ]; then
echo "TS:$TS FPS:$FPS BW:$BW FRAME:$FRAME"
fi
if [ -z "${TS//[0-9]}" ] && [ -n "$TS" ]; then
AGE=$(($(date +%s)-TS))
else
AGE=1000
fi
if [ "$AGE" -lt 4 ]; then
STATUS="Connected"
fi
fi
fi
# Calc CaptureBandwith in the same way as ZM in zm_monitor.cpp:
# unsigned int new_capture_bandwidth = (new_camera_bytes - last_camera_bytes)/(now-last_fps_time);
# Unfortunately, BASH can't trap a divide by zero so we have to check
# Get Filesize for Bandwidth calc. Ffmpeg buffers quite a lot so see if the file has changed
# size before calculating the Bandwidth.
FILESIZE=`stat -c%s "$NEW_VIDEO_PATH" 2>/dev/null`
#
# sometimes, the above read won't work. The file is too small/just started
# capturing, and therefore, nothing is read:
# ./zmrecord.sh: line 283: 1615896773 - : syntax error: operand expected (error token is "- ")
# so.. added a check here. Regex means "exists" and "numeric" tests plus >0 are all in one
#
if [ ${FILESIZE:-0} -gt ${LAST_FILESIZE:-0} ] && [[ $TS =~ [0-9]+ ]]
then
ELAPSED_SECONDS=$(($TS - $LAST_FPS_TIME))
if [ $ELAPSED_SECONDS > 0 ]
then
FILESIZE_INCREASE=$(( ${FILESIZE:-0} - ${LAST_FILESIZE:-0} ))
LAST_BW=$(( $FILESIZE_INCREASE / $ELAPSED_SECONDS ))
LAST_FPS_TIME=$TS
LAST_FILESIZE=$FILESIZE
fi
fi
SQL=" REPLACE INTO Monitor_Status (MonitorId, Status, CaptureFPS, CaptureBandwidth)
VALUES
('$MONITOR_ID','$STATUS', '$FPS', ${LAST_BW:-0})"
echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm
echo $SQL
}
# Main function -
function zmRecord() {
MONITOR_ID=$1
# Read Monitor Info From DB
IFS=$'\t'
read -r WIDTH HEIGHT READPATH STORAGEID EVENT_PREFIX <<< `mysql ${MYSQL_AUTH[@]} -NBqr zm -e "select Width,Height,Path,StorageId,EventPrefix from Monitors where Id=$MONITOR_ID"`
read -r STORAGE <<< `mysql ${MYSQL_AUTH[@]} -NBqr zm -e "select Path from Storage where Id=$STORAGEID"`
# Hmmmm.... on a fresh install of ZM 1.34, the Monitor has a StorageId of 0 but the Storage table
# starts at Id 1. Handle a blank Storage Path.
if [ -z "$STORAGE" -a $STORAGEID -eq 0 ]
then
read -r STORAGE <<< `mysql ${MYSQL_AUTH[@]} -NBqr zm -e "select Path from Storage where Id=1"`
fi
STORE_PATH=$STORAGE/$MONITOR_ID
if [ -z "$READPATH" -o -z "$STORE_PATH" -o -z "$STORAGE" ]; then
log_err "$0 Monitor Data Error. Got: Width $WIDTH Height $HEIGHT ReadPath $READPATH StorePath $STORE_PATH"
exit 1
fi
# create the working folders & files
# stats txt is constantly updated and placed in ram ( /dev/shm )
TMPFOLDER="$STORE_PATH/../$MONITOR_ID-zmrecordtmp"
FFMPEG_STAT_OUTPUT_FILE=/dev/shm/zmrecord-m$MONITOR_ID-stats.txt
FFMPEG_OUTPUT_FILENAME="$TMPFOLDER/%s.mp4"
mkdir -p "$TMPFOLDER"
rm "$FFMPEG_STAT_OUTPUT_FILE" 2>/dev/null
touch "$FFMPEG_STAT_OUTPUT_FILE"
chmod a+r "$FFMPEG_STAT_OUTPUT_FILE"
# Main loop exit trap triggered by EXIT / INT / TERM signals
RUNNING=1
trap 'RUNNING=0' EXIT
trap 'RUNNING=0' INT
trap 'RUNNING=0' TERM
# Main loop - start the ffmpeg processes and monitor
# regularly run updates to check ffmpegs video and stat output and transfer
# to zm database / file tree
log_inf "Monitor: $MONITOR_ID Starting zmrecord.sh"
FFMPEG_PID=-100
while [ "$RUNNING" = "1" ]; do
# testing this script one time my tmp folder vanished ( zm cleanup? )
# and this script was unable to recover so I added this
mkdir -p "$TMPFOLDER"
# start subprocesses / restart them if they stopped
if ! kill -0 "$FFMPEG_PID" 2>/dev/null; then
log_inf "Monitor: $MONITOR_ID Starting FFMPEG process"
run_ffmpeg "$MONITOR_ID" "$READPATH" "$FFMPEG_STAT_OUTPUT_FILE" "$RECORD_TIME" "$FFMPEG_OUTPUT_FILENAME" &
FFMPEG_PID=$!
fi
# check ffmpeg is actually working by monitoring the frame count
FFMPEG_STATS_FRAMES=`cat "$FFMPEG_STAT_OUTPUT_FILE" | cut -d " " -f4`
if [ "$PREV_FFMPEG_STATS_FRAMES" = "$FFMPEG_STATS_FRAMES" ]; then
if [ "$PREV_FFMPEG_STATS_FRAMES_SAMECOUNT" = "" ]; then
PREV_FFMPEG_STATS_FRAMES_SAMECOUNT=0
fi
PREV_FFMPEG_STATS_FRAMES_SAMECOUNT=$((PREV_FFMPEG_STATS_FRAMES_SAMECOUNT+1))
else
PREV_FFMPEG_STATS_FRAMES_SAMECOUNT=0
fi
PREV_FFMPEG_STATS_FRAMES="$FFMPEG_STATS_FRAMES"
if [ "$PREV_FFMPEG_STATS_FRAMES_SAMECOUNT" -gt 5 ]; then
if kill -0 "$FFMPEG_PID" 2>/dev/null; then
log_err "Monitor: $MONITOR_ID FFMPEG has stalled - killing"
kill $FFMPEG_PID
PREV_FFMPEG_STATS_FRAMES_SAMECOUNT=0
fi
fi
# run the video / db update polling functions
addCompleteVideosToDB "$TMPFOLDER" "$MONITOR_ID" "$STORAGEID" "$RECORD_TIME" "$WIDTH" "$HEIGHT" "$STORE_PATH" "$EVENT_PREFIX"
sleep 4
updateMonitorStatus "$MONITOR_ID" "$FFMPEG_STAT_OUTPUT_FILE" 0
addIncompleteVideosToDB "$TMPFOLDER" "$MONITOR_ID" "$STORAGEID" "$RECORD_TIME" "$WIDTH" "$HEIGHT" "$STORE_PATH" "$EVENT_PREFIX"
done
# Finish up
if ! kill -0 "$FFMPEG_PID" 2>/dev/null; then
kill "$FFMPEG_PID" 2>/dev/null
fi
addCompleteVideosToDB "$TMPFOLDER" "$MONITOR_ID" "$STORAGEID" "$RECORD_TIME" "$WIDTH" "$HEIGHT" "$STORE_PATH" "$EVENT_PREFIX"
updateMonitorStatus "$MONITOR_ID" "$FFMPEG_STAT_OUTPUT_FILE" 1
log_inf "Monitor: $MONITOR_ID Ended zmrecord.sh"
}
if [ $# -lt 1 ] || [[ ! $1 =~ ^[0-9]+$ ]] || [[ ! $2 =~ ^[01]$ ]] || [[ ! $3 =~ ^(|[0-9]+)$ ]]; then
echo "Syntax: $0 <Monitor Id> <0|1>(record audio or not) <Linked Monitor Id>"
echo "Script will search Linked Monitor for alarm frames, and add count to this monitor."
exit 1
fi
MONITOR_ID=$1
# record audio toggle
if [ $2 -eq 1 ]; then
DOAUDIO=(-c:a aac)
else
DOAUDIO=()
fi
# if provided, verify monitor id exists
if [ "$3" != "" ] && [ $3 -gt 0 ]; then
SQL="SELECT function from Monitors where id=$3;"
THIS_ID=`echo $SQL | mysql ${MYSQL_AUTH[@]} -NBqr zm`
if [ "$THIS_ID" == "" ]; then
echo "Can't find linked monitor ID ${3}."
exit 1
fi
if ! [[ $THIS_ID =~ (Modect|Mocord) ]]; then
echo "It doesn't seem like this Linked Monitor is doing any motion detection. Are you sure you want to use it?"
echo "(Continuing anyway...)"
fi
LINKED_MONITOR_ID=$3
fi
zmRecord $MONITOR_ID
Syntax: ./zmrecord.sh <Monitor Id> <0|1>(record audio or not) <Linked Monitor Id>
Script will search Linked Monitor for alarm frames, and add count to this monitor.
Seems not working correctly.
- should read something from a linked monitor to add what to the recorded high-res stream: not working, even I have a low-res stream in modect
- should maintain the counters of events in the main console page updated: not working.