0) { syslog(LOG_INFO, $output); } } if(isset($_GET['threshold'])) { $threshold = $_GET['threshold']; if (!is_numeric($threshold) || $threshold < 0 || $threshold > 1) { die('Invalid threshold value'); } $user = trim(shell_exec("awk -F: '/1000/{print $1}' /etc/passwd")); $home = trim(shell_exec("awk -F: '/1000/{print $6}' /etc/passwd")); $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 php7.4-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 = $_GET['apprise_notification_body']; $minimum_time_limit = $_GET['minimum_time_limit']; $flickr_api_key = $_GET['flickr_api_key']; $flickr_filter_email = $_GET["flickr_filter_email"]; $language = $_GET["language"]; $timezone = $_GET["timezone"]; $model = $_GET["model"]; $sf_thresh = $_GET["sf_thresh"]; $only_notify_species_names = $_GET['only_notify_species_names']; 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())) { shell_exec("sudo timedatectl set-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); } } // Update Language settings only if a change is requested if (file_exists('./scripts/thisrun.txt')) { $lang_config = parse_ini_file('./scripts/thisrun.txt'); } elseif (file_exists('./scripts/firstrun.ini')) { $lang_config = parse_ini_file('./scripts/firstrun.ini'); } if ($model != $lang_config['MODEL'] || $language != $lang_config['DATABASE_LANG']){ if(strlen($language) == 2){ $user = trim(shell_exec("awk -F: '/1000/{print $1}' /etc/passwd")); $home = trim(shell_exec("awk -F: '/1000/{print $6}' /etc/passwd")); // Archive old language file syslog_shell_exec("cp -f $home/BirdNET-Pi/model/labels.txt $home/BirdNET-Pi/model/labels.txt.old", $user); if($model == "BirdNET_GLOBAL_3K_V2.2_Model_FP16"){ // Install new language label file syslog_shell_exec("sudo chmod +x $home/BirdNET-Pi/scripts/install_language_label_nm.sh && $home/BirdNET-Pi/scripts/install_language_label_nm.sh -l $language", $user); } else { syslog_shell_exec("$home/BirdNET-Pi/scripts/install_language_label.sh -l $language", $user); } syslog(LOG_INFO, "Successfully changed language to '$language' and model to '$model'"); } } $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_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY='$apprise_notification_body'", $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("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents); $contents = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $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("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents); $contents2 = file_get_contents("./scripts/thisrun.txt"); $contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2); $contents2 = preg_replace("/LATITUDE=.*/", "LATITUDE=$latitude", $contents2); $contents2 = preg_replace("/LONGITUDE=.*/", "LONGITUDE=$longitude", $contents2); $contents2 = preg_replace("/BIRDWEATHER_ID=.*/", "BIRDWEATHER_ID=$birdweather_id", $contents2); $contents2 = preg_replace("/APPRISE_NOTIFICATION_TITLE=.*/", "APPRISE_NOTIFICATION_TITLE=\"$apprise_notification_title\"", $contents2); $contents2 = preg_replace("/APPRISE_NOTIFICATION_BODY=.*/", "APPRISE_NOTIFICATION_BODY='$apprise_notification_body'", $contents2); $contents2 = preg_replace("/APPRISE_NOTIFY_EACH_DETECTION=.*/", "APPRISE_NOTIFY_EACH_DETECTION=$apprise_notify_each_detection", $contents2); $contents2 = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES=.*/", "APPRISE_NOTIFY_NEW_SPECIES=$apprise_notify_new_species", $contents2); $contents2 = preg_replace("/APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=.*/", "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY=$apprise_notify_new_species_each_day", $contents2); $contents2 = preg_replace("/APPRISE_WEEKLY_REPORT=.*/", "APPRISE_WEEKLY_REPORT=$apprise_weekly_report", $contents2); $contents2 = preg_replace("/FLICKR_API_KEY=.*/", "FLICKR_API_KEY=$flickr_api_key", $contents2); $contents2 = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $contents2); $contents2 = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents2); $contents2 = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents2); $contents2 = preg_replace("/MODEL=.*/", "MODEL=$model", $contents2); $contents2 = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents2); $contents2 = preg_replace("/APPRISE_ONLY_NOTIFY_SPECIES_NAMES=.*/", "APPRISE_ONLY_NOTIFY_SPECIES_NAMES=\"$only_notify_species_names\"", $contents2); if($site_name != $config["SITE_NAME"]) { echo ""; } $fh = fopen("/etc/birdnet/birdnet.conf", "w"); $fh2 = fopen("./scripts/thisrun.txt", "w"); fwrite($fh, $contents); fwrite($fh2, $contents2); if(isset($apprise_input)){ $user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd"); $home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd"); $home = trim($home); $appriseconfig = fopen($home."/BirdNET-Pi/apprise.txt", "w"); fwrite($appriseconfig, $apprise_input); } syslog(LOG_INFO, "Restarting Services"); shell_exec("sudo restart_services.sh"); } if(isset($_GET['sendtest']) && $_GET['sendtest'] == "true") { $db = new SQLite3('./birds.db', SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE); $user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd"); $home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd"); $home = trim($home); if (file_exists('./thisrun.txt')) { $config = parse_ini_file('./thisrun.txt'); } elseif (file_exists('./firstrun.ini')) { $config = parse_ini_file('./firstrun.ini'); } $cf = explode("\n",$_GET['apprise_config']); $cf = "'".implode("' '", $cf)."'"; $statement0 = $db->prepare('SELECT * FROM detections WHERE Date == DATE(\'now\', \'localtime\') ORDER BY TIME DESC LIMIT 1'); $result0 = $statement0->execute(); while($todaytable=$result0->fetchArray(SQLITE3_ASSOC)) { $sciname = $todaytable['Sci_Name']; $comname = $todaytable['Com_Name']; $confidence = $todaytable['Confidence']; $filename = $todaytable['File_Name']; $date = $todaytable['Date']; $time = $todaytable['Time']; $week = $todaytable['Week']; $latitude = $todaytable['Lat']; $longitude = $todaytable['Lon']; $cutoff = $todaytable['Cutoff']; $sens = $todaytable['Sens']; $overlap = $todaytable['Overlap']; } $title = $_GET['apprise_notification_title']; $body = $_GET['apprise_notification_body']; if($config["BIRDNETPI_URL"] != "") { $filename = $config["BIRDNETPI_URL"]."?filename=".$filename; } else{ $filename = "http://birdnetpi.local/"."?filename=".$filename; } $attach=""; $exampleimage = "https://live.staticflickr.com/7430/27545810581_8bfa8289a3_c.jpg"; if (strpos($body, '$flickrimage') !== false) { $attach = "--attach ".$exampleimage; } if (strpos($body, '{') === false) { $exampleimage = ""; } $title = str_replace("\$sciname", $sciname, $title); $title = str_replace("\$comname", $comname, $title); $title = str_replace("\$confidence", $confidence, $title); $title = str_replace("\$listenurl", $filename, $title); $title = str_replace("\$date", $date, $title); $title = str_replace("\$time", $time, $title); $title = str_replace("\$week", $week, $title); $title = str_replace("\$latitude", $latitude, $title); $title = str_replace("\$longitude", $longitude, $title); $title = str_replace("\$cutoff", $cutoff, $title); $title = str_replace("\$sens", $sens, $title); $title = str_replace("\$overlap", $overlap, $title); $title = str_replace("\$flickrimage", $exampleimage, $title); $body = str_replace("\$sciname", $sciname, $body); $body = str_replace("\$comname", $comname, $body); $body = str_replace("\$confidence", $confidence, $body); $body = str_replace("\$listenurl", $filename, $body); $body = str_replace("\$date", $date, $body); $body = str_replace("\$time", $time, $body); $body = str_replace("\$week", $week, $body); $body = str_replace("\$latitude", $latitude, $body); $body = str_replace("\$longitude", $longitude, $body); $body = str_replace("\$cutoff", $cutoff, $body); $body = str_replace("\$sens", $sens, $body); $body = str_replace("\$overlap", $overlap, $body); $body = str_replace("\$flickrimage", $exampleimage, $body); echo "
".shell_exec($home."/BirdNET-Pi/birdnet/bin/apprise -vv --plugin-path ".$home."/.apprise/plugins "." -t '".escapeshellcmd($title)."' -b '".escapeshellcmd($body)."' ".$attach." ".$cf." ")."
"; die(); } ?>

Basic Settings


You cannot edit the settings for this installation'; exit; } else { $submittedpwd = $_SERVER['PHP_AUTH_PW']; $submitteduser = $_SERVER['PHP_AUTH_USER']; if($submittedpwd !== $caddypwd || $submitteduser !== 'birdnet'){ header('WWW-Authenticate: Basic realm="My Realm"'); header('HTTP/1.0 401 Unauthorized'); echo '
You cannot edit the settings for this installation
'; exit; } } ?>

Model


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

  
BirdNET_6K_GLOBAL_MODEL (2020)

This is the BirdNET-Lite model, with bird sound recognition for more than 6,000 species worldwide. This is the default option and will generally work very for people in most of the world.
BirdNET_GLOBAL_3K_V2.2_Model_FP16 (2022)

This is the BirdNET-Analyzer model, a newer work-in-progress project with aims to improve on the BirdNET-Lite model. Currently it only supports about 3,500 species worldwide, meaning for some regions (North America, Europe, Australia) it will usually outperform the BirdNET-Lite model, but for other regions it will be worse.

(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. Email Tim to request a BirdWeather ID


Notifications

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


$sciname
Scientific Name
$comname
Common Name
$confidence
Confidence Score
$listenurl
A link to the detection
$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"
$flickrimage
A preview image of the detected species from Flickr. Set your API key below.

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


' />
>
>
>
>






Bird Photos from Flickr



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


Localization


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

Time and Date

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