Files
AvianVisitors/scripts/extract_new_birdsounds.sh
T
2021-09-28 14:48:25 -04:00

159 lines
5.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Exit when any command fails
#set -x
set -e
# Keep track of the last executed command
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
# Echo an error message before exiting
trap 'echo "\"${last_command}\" command exited with code $?."' EXIT
# Remove temporary file
trap 'rm -f $TMPFILE' EXIT
source /etc/birdnet/birdnet.conf
# Set Variables
TMPFILE=$(mktemp)
# SCAN_DIRS are all directories marked "Analyzed"
SCAN_DIRS=($(find ${ANALYZED} -type d | sort ))
# This sets our while loop integer iterator 'a' -- it first checks whether
# there are any extractions, and if so, this instance of the extraction will
# start the 'a' value where the most recent instance left off.
# Ex: If the last extraction file is 189-%date%species.wav, 'a' will be 190.
# Else, 'a' starts at 1
if [ "$(find ${EXTRACTED} -name '*.wav' | wc -l)" -ge 1 ];then
a=$(( $( find "${EXTRACTED}" -name '*.wav' \
| awk -F "/" '{print $NF}' \
| cut -d'-' -f1 \
| sort -n \
| tail -n1 ) + 1 ))
else
a=1
fi
echo "Starting numbering at ${a}"
for h in "${SCAN_DIRS[@]}";do
echo "Creating the TMPFILE"
# The TMPFILE is created from each "Selection" txt file BirdNET creates
# within each "Analyzed" directory
# Field 1: Original WAVE file name
# Field 2: Extraction start time in seconds
# Field 3: Extraction end time in seconds
# Field 4: New WAVE file name to use
# Field 5: The species name
# Iterates over each "Analyzed" directory
for i in $(find ${h} -name '*txt' | sort );do
# Iterates over each '.txt' file found in each "Analyzed" directory
# to create the TMPFILE
sort -k 6n "$i" \
| awk '/Spect/ {print}' \
>> $TMPFILE
done
# The extraction reads each line of the TMPFILE and sets the variables ffmpeg
# will use.
while read -r line;do
a=$a
DATE="$(echo "${line}" \
| awk '{print $5}' \
| awk -F- '{print $1"-"$2"-"$3}')"
OLDFILE="$(echo "${line}" | awk '{print $5}')"
START="$(echo "${line}" | awk '{print $6}')"
END="$(echo "${line}" | awk '{print $7}')"
SPECIES=""$(echo ${line//\'} \
| awk '{for(i=11;i<=NF;++i)printf $i""FS ; print ""}' \
| cut -d'0' -f1 \
| xargs)""
NEWFILE="${SPECIES// /_}-${OLDFILE}"
NEWSPECIES_BYDATE="${EXTRACTED}/By_Date/${DATE}/${SPECIES// /_}"
NEWSPECIES_BYSPEC="${EXTRACTED}/By_Species/${SPECIES// /_}"
# If the extracted file already exists, increment the 'a' variable once
# but move onto the next line of the TMPFILE for extraction.
if [[ -f "${NEWSPECIES_BYDATE}/${a}-${NEWFILE}" ]];then
echo "Extraction exists. Moving on"
a=$((a+1))
continue
fi
echo "Checking for ${h}/${OLDFILE}"
# Before extracting the "Selection," the script checks to be sure the
# original WAVE file still exists.
[[ -f "${h}/${OLDFILE}" ]] || continue
echo "Checking for ${NEWSPECIES_BYDATE}"
# If a directory does not already exist for the species (by date),
# it is created
[[ -d "${NEWSPECIES_BYDATE}" ]] || mkdir -p "${NEWSPECIES_BYDATE}"
echo "Checking for ${NEWSPECIES_BYSPEC}"
# If a directory does not already exist for the species (by-species),
# it is created.
[[ -d "${NEWSPECIES_BYSPEC}" ]] || mkdir -p "${NEWSPECIES_BYSPEC}"
# If there are already 20 extracted entries for a given species
# for today, remove the oldest file and create the new one.
if [[ "$(find ${NEWSPECIES_BYDATE} | wc -l)" -ge 21 ]];then
echo "20 ${SPECIES}s, already! Removing the oldest by-date and making a new one"
cd ${NEWSPECIES_BYDATE} || exit 1
ls -1t . | tail -n +21 | xargs -r rm -vv
fi
echo "Extracting audio . . . "
# If the above tests have passed, then the extraction happens.
# After creating the extracted files by-date, and a directory tree
# structured by-species, symbolic links are made to populate the new
# directory.
ffmpeg -hide_banner -loglevel error -nostdin -i "${h}/${OLDFILE}" \
-acodec copy -ss "${START}" -to "${END}"\
"${NEWSPECIES_BYDATE}/${a}-${NEWFILE}"
if [[ "$(find ${NEWSPECIES_BYSPEC} | wc -l)" -ge 21 ]];then
echo "20 ${SPECIES}s, already! Removing the oldest by-species and making a new one"
cd ${NEWSPECIES_BYSPEC} || exit 1
ls -1t . | tail -n +21 | xargs -r rm -vv
ln -fs "${NEWSPECIES_BYDATE}/${a}-${NEWFILE}"\
"${NEWSPECIES_BYSPEC}/${a}-${NEWFILE}"
echo "Success! New extraction for ${SPECIES}"
else
ln -fs "${NEWSPECIES_BYDATE}/${a}-${NEWFILE}"\
"${NEWSPECIES_BYSPEC}/${a}-${NEWFILE}"
fi
# Finally, 'a' is incremented by one to allow multiple extractions per
# species per minute.
a=$((a + 1))
done < "${TMPFILE}"
echo -e "\n\n\nFINISHED!!! Processed extractions for ${h}"
# Once each line of the TMPFILE has been processed, the TMPFILE is emptied
# for the next iteration of the for loop.
>"${TMPFILE}"
# Rename files that have been processed so that they are not processed on the
# next extraction.
[[ -d "${PROCESSED}" ]] || mkdir "${PROCESSED}"
echo "Moving processed files to ${PROCESSED}"
mv -v ${h}/* ${PROCESSED} || continue
done
echo "Linking Processed files to "${EXTRACTED}/Processed" web directory"
# After all audio extractions have taken place, a directory is created to house
# the original WAVE and .txt files used for this extraction processs.
if [[ ! -L ${EXTRACTED}/Processed ]] || [[ ! -e ${EXTRACTED}/Processed ]];then
ln -sf ${PROCESSED} ${EXTRACTED}/Processed
fi
# That's all!
echo "Finished -- the extracted sections are in:
$(find -L ${EXTRACTED} -maxdepth 1)"