0) { syslog(LOG_INFO, $output); } } if(isset($_GET['threshold'])) { $threshold = $_GET['threshold']; if (!is_numeric($threshold) || $threshold < 0 || $threshold > 1) { die('Invalid threshold value'); } $command = "sudo -u $user ".$home."/BirdNET-Pi/birdnet/bin/python3 ".$home."/BirdNET-Pi/scripts/species.py --threshold $threshold 2>&1"; $output = shell_exec($command); echo $output; die(); } if(isset($_GET['restart_php']) && $_GET['restart_php'] == "true") { shell_exec("sudo service php*-fpm restart"); die(); } # Basic Settings if(isset($_GET["latitude"])){ $latitude = $_GET["latitude"]; $longitude = $_GET["longitude"]; $site_name = $_GET["site_name"]; $site_name = str_replace('"', "", $site_name); $site_name = str_replace('\'', "", $site_name); $birdweather_id = $_GET["birdweather_id"]; $apprise_input = $_GET['apprise_input']; $apprise_notification_title = $_GET['apprise_notification_title']; $apprise_notification_body = htmlspecialchars_decode($_GET['apprise_notification_body'], ENT_QUOTES); $minimum_time_limit = $_GET['minimum_time_limit']; $image_provider = $_GET["image_provider"]; $flickr_api_key = $_GET['flickr_api_key']; $flickr_filter_email = $_GET["flickr_filter_email"]; $language = $_GET["language"]; $info_site = $_GET["info_site"]; $color_scheme = $_GET["color_scheme"]; $timezone = $_GET["timezone"]; $model = $_GET["model"]; $sf_thresh = $_GET["sf_thresh"]; if(isset($_GET['data_model_version'])) { $data_model_version = 2; } else { $data_model_version = 1; } $only_notify_species_names = htmlspecialchars_decode($_GET['only_notify_species_names'], ENT_QUOTES); $only_notify_species_names_2 = htmlspecialchars_decode($_GET['only_notify_species_names_2'], ENT_QUOTES); if(isset($_GET['apprise_notify_each_detection'])) { $apprise_notify_each_detection = 1; } else { $apprise_notify_each_detection = 0; } if(isset($_GET['apprise_notify_new_species'])) { $apprise_notify_new_species = 1; } else { $apprise_notify_new_species = 0; } if(isset($_GET['apprise_notify_new_species_each_day'])) { $apprise_notify_new_species_each_day = 1; } else { $apprise_notify_new_species_each_day = 0; } if(isset($_GET['apprise_weekly_report'])) { $apprise_weekly_report = 1; } else { $apprise_weekly_report = 0; } if(isset($timezone) && in_array($timezone, DateTimeZone::listIdentifiers())) { # dpkg-reconfigure tzdata is a pain to run non-interactively, so we do it in two steps instead # tzlocal.get_localzone() will fail if the Debian specific /etc/timezone is not in sync shell_exec("sudo timedatectl set-timezone ".$timezone); if (file_exists('/etc/timezone')) { shell_exec("echo ".$timezone." | sudo tee /etc/timezone > /dev/null"); } $_SESSION['my_timezone'] = $timezone; date_default_timezone_set($timezone); echo ""; } // logic for setting the date and time based on user inputs from the form below if(isset($_GET['date']) && isset($_GET['time'])) { // can't set the date manually if it's getting it from the internet, disable ntp exec("sudo timedatectl set-ntp false"); // check if valid date and time $datetime = DateTime::createFromFormat('Y-m-d H:i', $_GET['date'] . ' ' . $_GET['time']); if ($datetime && $datetime->format('Y-m-d H:i') === $_GET['date'] . ' ' . $_GET['time']) { exec("sudo date -s '".$_GET['date']." ".$_GET['time']."'"); } } else { // user checked 'use time from internet if available,' so make sure that's on if(strlen(trim(exec("sudo timedatectl | grep \"NTP service: active\""))) == 0){ exec("sudo timedatectl set-ntp true"); sleep(3); } } $contents = file_get_contents("/etc/birdnet/birdnet.conf"); $contents = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents); $contents = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents); $contents = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents); $contents = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents); $contents = preg_replace("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents); $contents = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents); $contents = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents); $contents = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=.*/", "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=$apprise_notify_new_species_each_day", $contents); $contents = preg_replace("/APPRISE_WEEKLY_REPORT=.*/", "APPRISE_WEEKLY_REPORT=$apprise_weekly_report", $contents); $contents = preg_replace("/IMAGE_PROVIDER=.*/", "IMAGE_PROVIDER=$image_provider", $contents); $contents = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents); if(strlen($language) == 2){ $contents = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents); } $contents = preg_replace("/INFO_SITE=.*/", "INFO_SITE=$info_site", $contents); $contents = preg_replace("/COLOR_SCHEME=.*/", "COLOR_SCHEME=$color_scheme", $contents); $contents = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents); $contents = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents); $contents = preg_replace("/MODEL=.*/", "MODEL=$model", $contents); $contents = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents); $contents = preg_replace("/DATA_MODEL_VERSION=.*/", "DATA_MODEL_VERSION=$data_model_version", $contents); $contents = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents); $contents = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES_2=\"$only_notify_species_names_2\"", $contents); if($site_name != $config["SITE_NAME"] || $color_scheme != $config["COLOR_SCHEME"]) { echo ""; shell_exec("sudo systemctl restart chart_viewer.service"); // the sleep allows for the service to restart and image to be generated sleep(5); } $fh = fopen("/etc/birdnet/birdnet.conf", "w"); fwrite($fh, $contents); if(isset($apprise_input)){ $appriseconfig = fopen($home."/BirdNET-Pi/apprise.txt", "w"); fwrite($appriseconfig, $apprise_input); $apprise_config = $apprise_input; } if(isset($apprise_notification_body)){ $apprisebody = fopen($home."/BirdNET-Pi/body.txt", "w"); fwrite($apprisebody, $apprise_notification_body); } if ($model != $config['MODEL'] || $language != $config['DATABASE_LANG']){ if(strlen($language) == 2){ syslog_shell_exec("$home/BirdNET-Pi/scripts/install_language_label.sh", $user); syslog(LOG_INFO, "Successfully changed language to '$language' and model to '$model'"); } } syslog(LOG_INFO, "Restarting Services"); shell_exec("sudo restart_services.sh"); } if(isset($_GET['sendtest']) && $_GET['sendtest'] == "true") { $db = new SQLite3($home."/BirdNET-Pi/scripts/birds.db", SQLITE3_OPEN_READONLY); $db->busyTimeout(1000); $statement0 = $db->prepare('SELECT * FROM detections ORDER BY Date DESC, Time DESC LIMIT 1'); $result0 = $statement0->execute(); while($todaytable=$result0->fetchArray(SQLITE3_ASSOC)) { $detection = json_encode($todaytable); } $conf = $_GET['apprise_config']; $title = $_GET['apprise_notification_title']; $body = $_GET['apprise_notification_body']; $temp_det = tmpfile(); $t_det_path = stream_get_meta_data($temp_det)['uri']; chmod($t_det_path, 0644); fwrite($temp_det, $detection); $temp_conf = tmpfile(); $t_conf_path = stream_get_meta_data($temp_conf)['uri']; chmod($t_conf_path, 0644); fwrite($temp_conf, $conf); $temp_body = tmpfile(); $t_body_path = stream_get_meta_data($temp_body)['uri']; chmod($t_body_path, 0644); fwrite($temp_body, $body); $cmd = "sudo -u $user $home/BirdNET-Pi/birdnet/bin/python3 $home/BirdNET-Pi/scripts/send_test_notification.py --body $t_body_path --config $t_conf_path --title '" . escapeshellcmd($title) . "' --detection $t_det_path 2>&1"; $ret = shell_exec($cmd); echo "
".$ret."
"; fclose($temp_det); fclose($temp_conf); fclose($temp_body); die(); } // have to get the config again after we change the variables, so the UI reflects the changes too $config = get_config($force_reload=true); ?>

Basic Settings


Model


style="display: none" id="soft"> > [ Info here ]
[more info]

  
BirdNET_GLOBAL_6K_V2.4_Model_FP16 (2023)

This is the BirdNET-Analyzer model, the most advanced BirdNET model to date. Currently it supports over 6,000 species worldwide, giving quite good species coverage for people in most of the world.

BirdNET_6K_GLOBAL_MODEL (2020)

This is the BirdNET-Lite model, with bird sound recognition for more than 6,000 species worldwide. This has generally worse performance than the newer models but is kept as a legacy option.

[ In-depth technical write-up on the models here ]

Location

(Optional)

Set your Latitude and Longitude to 4 decimal places. Get your coordinates here.


BirdWeather


BirdWeather.com is a weather map for bird sounds. Stations around the world supply audio and video streams to BirdWeather where they are then analyzed by BirdNET and compared to eBird Grid data. BirdWeather catalogues the bird audio and spectrogram visualizations so that you can listen to, view, and read about birds throughout the world.

To request a BirdWeather Token, You'll first need to create an account - https://app.birdweather.com/
Once that's done - you can go to - https://app.birdweather.com/account/stations
Make sure that the Latitude and Longitude match what is in your BirdNET-Pi configuration.

NOTE - by using your BirdWeather Token - you are consenting to sharing your soundscapes and detections with BirdWeather


Notifications

Apprise Notifications can be setup and enabled for 90+ notification services. Each service should be on its own line.


$sciname
Scientific Name
$comname
Common Name
$confidence
Confidence Score
$confidencepct
Confidence Score as a percentage (eg. 0.91 => 91)
$listenurl
A link to the detection
$friendlyurl
A masked link to the detection. Only useful for services that support Markdown (e.g. Discord).
$date
Date
$time
Time
$week
Week
$latitude
Latitude
$longitude
Longitude
$cutoff
Minimum Confidence set in "Advanced Settings"
$sens
Sigmoid Sensitivity set in "Advanced Settings"
$overlap
Overlap set in "Advanced Settings"
$image
An image of the detected species from a photo source, see below.
$reason
The reason a notification was sent

Use the variables defined above to customize your notification title and body.


>
>
>
>







Bird Photo Source


Set your Flickr API key to enable the display of bird images next to detections. Get your key here.




Localization

! Only modify this at initial setup !


Additional Info

allaboutbirds.org default
ebirds.org has more European species


Color scheme

Note: when changing themes the daily chart may need a page refresh before updating.


0) { $checkedvalue = "checked"; $disabledvalue = "disabled"; } else { $checkedvalue = ""; $disabledvalue = ""; } ?>

Time and Date

If connected to the internet, retrieve time automatically? >
> >