Add base daemon scripts
This commit is contained in:
parent
43e4ebeef3
commit
17b2d3d2b1
|
@ -1,3 +1,7 @@
|
|||
var/
|
||||
/.venv/
|
||||
/analyzer/
|
||||
|
||||
.env
|
||||
|
||||
species_list.txt
|
11
INSTALL.md
11
INSTALL.md
|
@ -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
|
||||
|
||||
|
|
16
README.md
16
README.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue