eb86faddcd
with low / no disk space and be unable to "escape." In the event of a backlog, the loop in birdnet_analysis.sh runs continuously, which means analyzed files do not get moved, which means in turn extract_new_birdsounds.sh cannot create mp3 extractions and move the processed files again, which would allow them to be cleaned up by the cron jobs. This patch is the obvious fix, i.e. to just limit the maximum amount of files birdnet_analysis.sh can process to 20. This should be a good trade off given the small overhead of listing files etc before the main loop begins - note that for the "normal" case of no backlog, birdnet_analysis usually exits after a single analysis anyway.
197 lines
5.8 KiB
Bash
Executable File
197 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env -S --default-signal=PIPE bash
|
|
# Runs BirdNET-Lite
|
|
#set -x
|
|
source /etc/birdnet/birdnet.conf
|
|
# Document this run's birdnet.conf settings
|
|
# Make a temporary file to compare the current birdnet.conf with
|
|
# the birdnet.conf as it was the last time this script was called
|
|
my_dir=$HOME/BirdNET-Pi/scripts
|
|
if [ -z ${THIS_RUN} ];then THIS_RUN=$my_dir/thisrun.txt;fi
|
|
[ -f ${THIS_RUN} ] || touch ${THIS_RUN} && chmod g+w ${THIS_RUN}
|
|
if [ -z ${LAST_RUN} ];then LAST_RUN=$my_dir/lastrun.txt;fi
|
|
[ -z ${LATITUDE} ] && echo "LATITUDE not set, exiting 1" && exit 1
|
|
[ -z ${LONGITUDE} ] && echo "LONGITUDE not set, exiting 1" && exit 1
|
|
make_thisrun() {
|
|
sleep .4
|
|
awk '!/#/ && !/^$/ {print}' /etc/birdnet/birdnet.conf \
|
|
> >(tee "${THIS_RUN}")
|
|
sleep .5
|
|
}
|
|
make_thisrun &> /dev/null
|
|
if ! diff ${LAST_RUN} ${THIS_RUN};then
|
|
echo "The birdnet.conf file has changed"
|
|
if grep REC <(diff $LAST_RUN $THIS_RUN);then
|
|
echo "Recording element changed -- restarting 'birdnet_recording.service'"
|
|
sudo systemctl stop birdnet_recording.service
|
|
sudo rm -rf ${RECS_DIR}/$(date +%B-%Y/%d-%A)/*
|
|
sudo systemctl start birdnet_recording.service
|
|
fi
|
|
cat ${THIS_RUN} > ${LAST_RUN}
|
|
fi
|
|
|
|
INCLUDE_LIST="$HOME/BirdNET-Pi/include_species_list.txt"
|
|
EXCLUDE_LIST="$HOME/BirdNET-Pi/exclude_species_list.txt"
|
|
if [ ! -f ${INCLUDE_LIST} ];then
|
|
touch ${INCLUDE_LIST} &&
|
|
chmod g+rw ${INCLUDE_LIST}
|
|
fi
|
|
if [ ! -f ${EXCLUDE_LIST} ];then
|
|
touch ${EXCLUDE_LIST} &&
|
|
chmod g+rw ${EXCLUDE_LIST}
|
|
fi
|
|
if [ "$(du ${INCLUDE_LIST} | awk '{print $1}')" -lt 4 ];then
|
|
INCLUDE_LIST=null
|
|
fi
|
|
if [ "$(du ${EXCLUDE_LIST} | awk '{print $1}')" -lt 4 ];then
|
|
EXCLUDE_LIST=null
|
|
fi
|
|
|
|
# Create an array of the audio files
|
|
# Takes one argument:
|
|
# - {DIRECTORY}
|
|
get_files() {
|
|
files=($( find ${1} -maxdepth 1 -name '*wav' ! -size 0\
|
|
| sort \
|
|
| head -n 20 \
|
|
| awk -F "/" '{print $NF}' ))
|
|
[ -n "${files[1]}" ] && echo "Files loaded"
|
|
}
|
|
|
|
# Move all files that have been analyzed already into newly created "Analyzed"
|
|
# directory
|
|
# Takes one argument:
|
|
# - {DIRECTORY}
|
|
move_analyzed() {
|
|
for i in "${files[@]}";do
|
|
j="${i}.csv"
|
|
if [ -f "${1}/${j}" ];then
|
|
if [ ! -d "${1}-Analyzed" ];then
|
|
mkdir -p "${1}-Analyzed" && echo "'Analyzed' directory created"
|
|
fi
|
|
mv "${1}/${i}" "${1}-Analyzed/"
|
|
mv "${1}/${j}" "${1}-Analyzed/"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Run BirdNET-Lite on the WAVE files from get_files()
|
|
# Uses one argument:
|
|
# - {DIRECTORY}
|
|
run_analysis() {
|
|
PYTHON_VIRTUAL_ENV="$HOME/BirdNET-Pi/birdnet/bin/python3"
|
|
DIR="$HOME/BirdNET-Pi/scripts"
|
|
|
|
sleep .5
|
|
|
|
### TESTING NEW WEEK CALCULATION
|
|
WEEK_OF_YEAR="$(echo "($(date +%m)-1) * 4" | bc -l)"
|
|
DAY_OF_MONTH="$(date +%d)"
|
|
if [ ${DAY_OF_MONTH} -le 7 ];then
|
|
WEEK="$(echo "${WEEK_OF_YEAR} + 1" |bc -l)"
|
|
elif [ ${DAY_OF_MONTH} -le 14 ];then
|
|
WEEK="$(echo "${WEEK_OF_YEAR} + 2" |bc -l)"
|
|
elif [ ${DAY_OF_MONTH} -le 21 ];then
|
|
WEEK="$(echo "${WEEK_OF_YEAR} + 3" |bc -l)"
|
|
elif [ ${DAY_OF_MONTH} -ge 22 ];then
|
|
WEEK="$(echo "${WEEK_OF_YEAR} + 4" |bc -l)"
|
|
fi
|
|
|
|
for i in "${files[@]}";do
|
|
[ ! -f ${1}/${i} ] && continue
|
|
echo "${1}/${i}" > $HOME/BirdNET-Pi/analyzing_now.txt
|
|
[ -z ${RECORDING_LENGTH} ] && RECORDING_LENGTH=15
|
|
echo "RECORDING_LENGTH set to ${RECORDING_LENGTH}"
|
|
itr=0
|
|
until [ -z "$(lsof -t ${1}/${i})" ];do
|
|
itr=$((itr+1))
|
|
if [ $itr -eq $(($RECORDING_LENGTH * 3)) ]; then
|
|
echo "Maximum number of attempts exceeded. Exiting & restarting service."
|
|
exit
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
if ! grep 5050 <(netstat -tulpn 2>&1) &> /dev/null 2>&1;then
|
|
echo "Waiting for socket"
|
|
until grep 5050 <(netstat -tulpn 2>&1) &> /dev/null 2>&1;do
|
|
sleep 1
|
|
done
|
|
fi
|
|
# prepare optional parameters for analyze.py
|
|
if [ -f ${INCLUDE_LIST} ]; then
|
|
INCLUDEPARAM="--include_list ${INCLUDE_LIST}"
|
|
else
|
|
INCLUDEPARAM=""
|
|
fi
|
|
if [ -f ${EXCLUDE_LIST} ]; then
|
|
EXCLUDEPARAM="--exclude_list ${EXCLUDE_LIST}"
|
|
else
|
|
EXCLUDEPARAM=""
|
|
fi
|
|
if [ ! -z $BIRDWEATHER_ID ]; then
|
|
BIRDWEATHER_ID_PARAM="--birdweather_id ${BIRDWEATHER_ID}"
|
|
BIRDWEATHER_ID_LOG="--birdweather_id \"IN_USE\""
|
|
else
|
|
BIRDWEATHER_ID_PARAM=""
|
|
BIRDWEATHER_ID_LOG=""
|
|
fi
|
|
echo $PYTHON_VIRTUAL_ENV "$DIR/analyze.py" \
|
|
--i "${1}/${i}" \
|
|
--o "${1}/${i}.csv" \
|
|
--lat $(echo "${LATITUDE}" | awk '{print int($1+0.5)}').XX \
|
|
--lon $(echo "${LONGITUDE}" | awk '{print int($1+0.5)}').XX \
|
|
--week "${WEEK}" \
|
|
--overlap "${OVERLAP}" \
|
|
--sensitivity "${SENSITIVITY}" \
|
|
--min_conf "${CONFIDENCE}" \
|
|
${INCLUDEPARAM} \
|
|
${EXCLUDEPARAM} \
|
|
${BIRDWEATHER_ID_LOG}
|
|
$PYTHON_VIRTUAL_ENV $DIR/analyze.py \
|
|
--i "${1}/${i}" \
|
|
--o "${1}/${i}.csv" \
|
|
--lat "${LATITUDE}" \
|
|
--lon "${LONGITUDE}" \
|
|
--week "${WEEK}" \
|
|
--overlap "${OVERLAP}" \
|
|
--sensitivity "${SENSITIVITY}" \
|
|
--min_conf "${CONFIDENCE}" \
|
|
${INCLUDEPARAM} \
|
|
${EXCLUDEPARAM} \
|
|
${BIRDWEATHER_ID_PARAM}
|
|
if [ ! -z $HEARTBEAT_URL ]; then
|
|
echo "Performing Heartbeat"
|
|
IP=`curl -s ${HEARTBEAT_URL}`
|
|
echo "Heartbeat: $IP"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# The three main functions
|
|
# Takes one argument:
|
|
# - {DIRECTORY}
|
|
run_birdnet() {
|
|
get_files "${1}"
|
|
move_analyzed "${1}"
|
|
run_analysis "${1}"
|
|
}
|
|
|
|
until grep 5050 <(netstat -tulpn 2>&1) &> /dev/null 2>&1;do
|
|
sleep 1
|
|
done
|
|
|
|
if [ $(find ${RECS_DIR}/StreamData -maxdepth 1 -name '*wav' 2>/dev/null| wc -l) -gt 0 ];then
|
|
find $RECS_DIR -maxdepth 1 -name '*wav' -type f -size 0 -delete
|
|
run_birdnet "${RECS_DIR}/StreamData"
|
|
fi
|
|
|
|
YESTERDAY="$RECS_DIR/$(date --date="yesterday" "+%B-%Y/%d-%A")"
|
|
TODAY="$RECS_DIR/$(date "+%B-%Y/%d-%A")"
|
|
if [ $(find ${YESTERDAY} -name '*wav' 2>/dev/null | wc -l) -gt 0 ];then
|
|
find $YESTERDAY -name '*wav' -type f -size 0 -delete
|
|
run_birdnet "${YESTERDAY}"
|
|
elif [ $(find ${TODAY} -name '*wav' 2>/dev/null | wc -l) -gt 0 ];then
|
|
find $TODAY -name '*wav' -type f -size 0 -delete
|
|
run_birdnet "${TODAY}"
|
|
fi
|