[BUG] api: resolve recording/spectrogram dirs by normalized species name

This commit is contained in:
Twarner491
2026-06-05 16:28:18 -07:00
parent b8b97893a1
commit 4e43b5ee69
2 changed files with 34 additions and 6 deletions
+19 -3
View File
@@ -141,16 +141,32 @@ if ($common === null) {
// subdirectory named exactly $common, return the newest .mp3 inside. // subdirectory named exactly $common, return the newest .mp3 inside.
function newest_recording(string $rootDir, string $common): ?string { function newest_recording(string $rootDir, string $common): ?string {
if (!is_dir($rootDir)) return null; if (!is_dir($rootDir)) return null;
// Match species dirs by a normalised name so apostrophes / case /
// punctuation don't matter: "Anna's_Hummingbird" == "Annas_Hummingbird"
// == "annas hummingbird". BirdNET-Pi isn't consistent about the
// apostrophe in species dir names, which is why a bird like Anna's
// Hummingbird could 404 while every other species played fine.
$norm = function (string $s): string {
return preg_replace('/[^a-z0-9]/', '', strtolower($s));
};
$want = $norm($common);
$dates = scandir($rootDir, SCANDIR_SORT_DESCENDING); $dates = scandir($rootDir, SCANDIR_SORT_DESCENDING);
if (!$dates) return null; if (!$dates) return null;
foreach ($dates as $date) { foreach ($dates as $date) {
if ($date[0] === '.') continue; if ($date[0] === '.') continue;
$speciesDir = "$rootDir/$date/$common"; $dayDir = "$rootDir/$date";
if (!is_dir($speciesDir)) continue; if (!is_dir($dayDir)) continue;
$speciesDir = null;
foreach (scandir($dayDir) as $sub) {
if ($sub[0] === '.' || !is_dir("$dayDir/$sub")) continue;
if ($norm($sub) === $want) { $speciesDir = "$dayDir/$sub"; break; }
}
if ($speciesDir === null) continue;
$files = scandir($speciesDir, SCANDIR_SORT_DESCENDING); $files = scandir($speciesDir, SCANDIR_SORT_DESCENDING);
if (!$files) continue; if (!$files) continue;
foreach ($files as $f) { foreach ($files as $f) {
if (substr($f, -4) === '.mp3') { // Skip zero-byte / truncated files a purge may have left behind.
if (substr($f, -4) === '.mp3' && @filesize("$speciesDir/$f") >= 64) {
return "$speciesDir/$f"; return "$speciesDir/$f";
} }
} }
+15 -3
View File
@@ -128,16 +128,28 @@ $common = resolve_common($sci) ?? str_replace(' ', '_', $sci);
function newest_spectrogram(string $rootDir, string $common): ?string { function newest_spectrogram(string $rootDir, string $common): ?string {
if (!is_dir($rootDir)) return null; if (!is_dir($rootDir)) return null;
// Normalised match so apostrophes / case don't matter - same fix as
// recording.php (e.g. Anna's_Hummingbird vs Annas_Hummingbird).
$norm = function (string $s): string {
return preg_replace('/[^a-z0-9]/', '', strtolower($s));
};
$want = $norm($common);
$dates = scandir($rootDir, SCANDIR_SORT_DESCENDING); $dates = scandir($rootDir, SCANDIR_SORT_DESCENDING);
if (!$dates) return null; if (!$dates) return null;
foreach ($dates as $date) { foreach ($dates as $date) {
if ($date[0] === '.') continue; if ($date[0] === '.') continue;
$speciesDir = "$rootDir/$date/$common"; $dayDir = "$rootDir/$date";
if (!is_dir($speciesDir)) continue; if (!is_dir($dayDir)) continue;
$speciesDir = null;
foreach (scandir($dayDir) as $sub) {
if ($sub[0] === '.' || !is_dir("$dayDir/$sub")) continue;
if ($norm($sub) === $want) { $speciesDir = "$dayDir/$sub"; break; }
}
if ($speciesDir === null) continue;
$files = scandir($speciesDir, SCANDIR_SORT_DESCENDING); $files = scandir($speciesDir, SCANDIR_SORT_DESCENDING);
if (!$files) continue; if (!$files) continue;
foreach ($files as $f) { foreach ($files as $f) {
if (substr($f, -4) === '.png') { if (substr($f, -4) === '.png' && @filesize("$speciesDir/$f") >= 64) {
return "$speciesDir/$f"; return "$speciesDir/$f";
} }
} }