Add base daemon scripts

This commit is contained in:
Samuel Ortion 2022-08-13 07:48:06 +02:00
parent 43e4ebeef3
commit 17b2d3d2b1
13 changed files with 232 additions and 42 deletions

6
.gitignore vendored
View File

@ -1,3 +1,7 @@
var/
/.venv/
/analyzer/
/analyzer/
.env
species_list.txt

View File

@ -1,5 +1,13 @@
# Installation Guide for BirdNET-stream
This guide allow you to install BirdNET-stream step by step on your debian based system.
For a one-liner installation, you can use the following command:
```bash
curl -sL https://raw.githubusercontent.com/birdnet-stream/birdnet-stream/master/install.sh | bash
```
## Requirements
- git
@ -25,7 +33,8 @@ sudo apt-get install ffmpeg
### Clone BirdNET-stream repository
```bash
git clone https://forge.chapril.org/UncleSamulus/BirdNET-stream.git
git clone --recurse-submodules https://forge.chapril.org/UncleSamulus/BirdNET-stream.git
```
### Setup python virtualenv and packages

View File

@ -6,6 +6,22 @@
<img src="./media/logo.svg" alt="BirdNET-stream logo image IA generated" style="width: 500px">
</p>
## Introduction
BirdNET-stream record sound on Linux computer and analyze it with the help of the BirdNET algorithm. It extracts most interesting bird songs and calls accessible in a webapp.
## Install
On debian based system, you can install BirdNET-stream with the following command:
```bash
curl -sL https://raw.githubusercontent.com/birdnet-stream/birdnet-stream/master/install.sh | bash
```
For finer control, or to adapt to your system, you can follow the instructions in the [INSTALL.md](./INSTALL.md) file.
## Usage
## Acknoledgements
- [BirdNET](https://birdnet.cornell.edu) on which this project relies

View File

@ -39,35 +39,32 @@ check_prerequisites() {
mkdir -p "${CHUNK_FOLDER}/out"
fi
fi
fi
fi
fi
if [[ -z ${SPECIES_LIST} ]];
then
if [[ -z ${SPECIES_LIST} ]]; then
echo "SPECIES_LIST is not set"
exit 1
fi
if [[ -f $PYTHON_EXECUTABLE ]];
then
if [[ -f ${PYTHON_EXECUTABLE} ]]; then
if $verbose; then
echo "Python executable found: $PYTHON_EXECUTABLE"
echo "Python executable found: ${PYTHON_EXECUTABLE}"
fi
else
echo "Python executable not found: $PYTHON_EXECUTABLE"
echo "Python executable not found: ${PYTHON_EXECUTABLE}"
exit 1
fi
}
# Get array of audio chunks to be processed
get_chunk_list() {
find "$CHUNK_FOLDER/in" -type f -name '*.wav' -exec basename {} \; ! -size 0 | sort
find "${CHUNK_FOLDER}/in" -type f -name '*.wav' -exec basename {} \; ! -size 0 | sort
}
# Perform audio chunk analysis on one chunk
analyze_chunk() {
chunk_name=$1
chunk_path="$CHUNK_FOLDER/in/$chunk_name"
output_dir="$CHUNK_FOLDER/out/$chunk_name.d"
chunk_path="${CHUNK_FOLDER}/in/$chunk_name"
output_dir="${CHUNK_FOLDER}/out/$chunk_name.d"
mkdir -p "$output_dir"
date=$(echo $chunk_name | cut -d'_' -f2)
week=$(./daemon/weekof.sh $date)
@ -78,8 +75,8 @@ analyze_chunk() {
analyze_chunks() {
for chunk_name in $(get_chunk_list); do
analyze_chunk $chunk_name
chunk_path="$CHUNK_FOLDER/in/$chunk_name"
mv $chunk_path "$CHUNK_FOLDER/out/$chunk_name"
chunk_path="${CHUNK_FOLDER}/in/$chunk_name"
mv $chunk_path "${CHUNK_FOLDER}/out/$chunk_name"
done
}
@ -87,4 +84,4 @@ analyze_chunks() {
chunks=$(get_chunk_list)
# Analyze all chunks in working directory
analyze_chunks $chunks
analyze_chunks $chunks

76
daemon/birdnet_clean.sh Executable file
View File

@ -0,0 +1,76 @@
#! /usr/bin/env bash
##
## Clean up var folder from useless files
##
config_filepath="./config/analyzer.conf"
if [ -f "$config_filepath" ]; then
source "$config_filepath"
else
echo "Config file not found: $config_filepath"
exit 1
fi
wav2dir_name() {
wav_path=$1
dir_name=$(basename "$wav_path" .wav)
echo "$dir_name"
}
# Clean out folder from empty audio
clean() {
rm -rf $(junk)
}
# Check if string contains string
mem() {
string=$2
substring=$1
if [[ "$string" == *"$substring"* ]]; then
echo "true"
else
echo "false"
fi
}
# Get list of junk files
junk() {
# Get all empty files from treatement folder
find "${CHUNK_FOLDER}/out" -type f -name '*.wav' -size 0
for file in $junk; do
folder=$(wav2dir_name "$file")
if [[ -d $folder ]]; then
junk="$junk $folder"
fi
done
# Get all empty files from record folder
junk=$(find "${CHUNK_FOLDER}/in" -type f -name '*.wav' -exec basename {} \; ! -size 0)
# Get all empty treatment directories
junk="$junk $(find ${CHUNK_FOLDER}/out -type d -empty)"
# Get all empty record directories
treatement_folder=$(find "${CHUNK_FOLDER}/out" -type d ! -empty)
for folder in $treatement_folder; do
if ! $(mem $folder $junk) && $(no_bird_in_model_output $folder); then
junk="$junk $folder"
fi
done
echo "$junk"
}
no_bird_in_model_output() {
folder=$1
output="${folder}/model.out.csv"
lines=$(wc -l < "$output")
if [[ $lines -eq 1 ]]; then
echo "true"
else
echo "false"
fi
}
main() {
clean
}
main

View File

@ -1,7 +1,6 @@
#! /usr/bin/env bash
record_chunk()
{
record_chunk() {
DEVICE=$1
DURATION=$2
ffmpeg -f pulse -i ${DEVICE} -t ${DURATION} -vn -acodec pcm_s16le -ac 1 -ar 48000 file:${CHUNK_FOLDER}/in/birdnet_$(date "+%Y%m%d_%H%M%S").wav
@ -23,6 +22,16 @@ if [[ -z $AUDIO_DEVICE ]]; then
exit 1
fi
check_folder() {
if [[ ! -d "${CHUNK_FOLDER}" ]]; then
echo "CHUNK_FOLDER does not exist: ${CHUNK_FOLDER}"
echo "Creating recording dir"
mkdir -p "${CHUNK_FOLDER}/in"
fi
}
check_folder
while true; do
record_chunk $AUDIO_DEVICE $RECORDING_DURATION
done
done

View File

View File

@ -0,0 +1,15 @@
# Launch BirdNET-Analyzer on the previously recorded audio chunks
[Unit]
Description=BirdNET-stream Analyzis
[Service]
User=$USER
Group=$USER
ExecStart=/home/$USER/BirdNET-Analyzer/deamon/birdnet_analysis.sh
Restart=always
RestartSec=3
Type=simple
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
# BirdNET recording script launcher service
[Unit]
Description=BirdNET-stream recording
[Service]
User=1000
Group=1000
ExecStart="bash /home/$USER/BirdNET-stream/daemon/birdnet_recording.sh"
Restart=always
RestartSec=3
Type=simple
[Install]
WantedBy=multi-user.target

View File

@ -1,5 +1,6 @@
#! /usr/bin/env bash
# Take a week with format "YYYY-MM-DD" and return the week number.
function weekof()
{
local date=$1

72
install.sh Executable file
View File

@ -0,0 +1,72 @@
#! /usr/bin/env bash
set -X
set -e
DEBUG=${DEBUG:-0}
# Standard Installation Script for BirdNET-stream for Debian Based Linux distros
REQUIREMENTS="git ffmpeg python3-pip python3-dev"
REPOSITORY="https://github.com/UncleSamulus/BirdNET-stream.git"
PYTHON_VENV=".venv/birdnet-stream"
# Update system
update() {
sudo apt-get update
sudo apt-get upgrade
}
debug() {
if [ $DEBUG -eq 1 ]; then
echo "$1"
fi
}
install_requirements() {
if
requirements=$1
# Install requirements
missing_requirements=""
for requirement in $requirements; do
if ! dpkg -s $requirement >/dev/null 2>&1; then
missing_requirements="$missing_requirements $requirement"
fi
done
if [ -n "$missing_requirements" ]; then
debug "Installing missing requirements: $missing_requirements"
sudo apt-get install $missing_requirements
fi
}
# Install BirdNET-stream
install_birdnetstream() {
# Clone BirdNET-stream
debug "Cloning BirdNET-stream from $REPOSITORY"
git clone --recurse-submodules $REPOSITORY
# Install BirdNET-stream
cd BirdNET-stream
debug "Creating python3 virtual environment '$PYTHON_VENV'"
python3 -m venv $PYTHON_VENV
debug "Activating $PYTHON_VENV"
source .venv/birdnet-stream/bin/activate
debug "Installing python packages"
pip install -U pip
pip install -r requirements.txt
}
# Install systemd services
install_birdnetstream_services() {
debug "Setting up BirdNET stream systemd services"
sudo ln -s $PWD/BirdNET-stream/daemon/systemd/birdnet_recording.service /etc/systemd/system/birdnet_recording.service
sudo ln -s $PWD/BirdNET-stream/daemon/systemd/birdnet_analyzis.service /etc/systemd/system/birdnet_analyzis.service
sudo systemctl daemon-reload
sudo systemctl enable --now birdnet_recording.service birdnet_analyzis.service
}
main() {
install_requirements $REQUIREMENTS
install_birdnetstream
install_birdnetstream_services
}
main

View File

@ -1,24 +0,0 @@
#! /usr/bin/env bash
# Load config file
config_filepath="./config/analyzer.conf"
if [ -f "$config_filepath" ]; then
source "$config_filepath"
else
echo "Config file not found: $config_filepath"
exit 1
fi
# Remove all files from the temporary record directory
function clean_record_dir()
{
rm -rf "$CHUNK_FOLDER/in/*.wav"
}
function remove_empty_records()
{
find $CHUNK_FOLDER/in -maxdepth 1 -name '*wav' -type f -size 0 -delete
}
remove_empty_records