Spaces:
Paused
Paused
File size: 15,428 Bytes
5023401 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | import gradio as gr
from transformers import pipeline
import numpy as np
from datetime import datetime
# Load the audio classification model
classifier = pipeline(
"audio-classification",
model="dima806/bird_sounds_classification",
device=-1,
)
# Bird information database (15 species with descriptions)
BIRD_INFO = {
"Great Tinamou": {
"habitat": "Tropical and subtropical lowland forests from southern Mexico to northern South America.",
"song": "A series of tremulous, haunting whistles that echo through the forest - one of the most recognizable sounds of the neotropical lowlands.",
"range": "Southern Mexico through Central America to northern South America, including Brazil and Peru.",
"fun_fact": "Despite being a ground-dwelling bird, the Great Tinamou roosts in trees at night. Its eggs are among the most beautiful in the bird world - glossy turquoise-blue.",
},
"Plain Chachalaca": {
"habitat": "Brushy woodland edges, thickets, and riparian areas. The only chachalaca regularly found in the United States (southern Texas).",
"song": "A loud, raucous CHA-cha-LAC repeated in chorus by groups - unmistakable once you've heard it. Often called at dawn.",
"range": "Southern Texas through Mexico to Costa Rica.",
"fun_fact": "Plain Chachalacas are one of the few species in this model's list that can actually be seen in the US - in the Rio Grande Valley of Texas.",
},
"Crested Guan": {
"habitat": "Mountain forests and cloud forests, typically at elevations of 500-2,500 meters.",
"song": "A variety of honking and trumpeting calls, especially loud during breeding season.",
"range": "Southern Mexico through Central America to western South America.",
"fun_fact": "Crested Guans are important seed dispersers for many tropical tree species. They swallow fruits whole and spread seeds through the forest.",
},
"Andean Guan": {
"habitat": "Cloud forests and humid montane forests of the Andes, typically between 1,500 and 3,500 meters elevation.",
"song": "Deep honking calls that carry through mountain valleys, often given in the early morning.",
"range": "Andes from Venezuela south through Colombia, Ecuador, Peru, and Bolivia.",
"fun_fact": "The Andean Guan is a canopy specialist that rarely descends to the ground, moving through the treetops to feed on fruit and leaves.",
},
"Little Tinamou": {
"habitat": "Dense undergrowth of tropical forests. Extremely secretive and almost never seen despite being common.",
"song": "A long, tremulous whistle that rises and falls - one of the most frequently heard but least seen birds in its range.",
"range": "Southern Mexico through Central America to South America, as far south as Brazil.",
"fun_fact": "Little Tinamous are heard far more often than seen. They freeze when threatened and rely on their camouflage, only flushing at the last moment.",
},
"Solitary Tinamou": {
"habitat": "Interior of humid tropical forests, usually on the forest floor.",
"song": "A mournful, descending whistle that sounds almost electronic - quite eerie when heard in the deep forest.",
"range": "Central America through northern South America.",
"fun_fact": "True to its name, the Solitary Tinamou is almost always found alone. Males incubate the eggs and raise the chicks by themselves.",
},
"Highland Tinamou": {
"habitat": "Cloud forests and montane forests, from 1,200 to 3,000 meters elevation.",
"song": "A clear, descending series of whistles. Sometimes described as sounding like someone playing a slow scale on a flute.",
"range": "Mountains of Costa Rica and Panama through the Andes to Bolivia.",
"fun_fact": "Highland Tinamous have been recorded at higher elevations than almost any other tinamou species.",
},
"Grey-headed Chachalaca": {
"habitat": "Dry forests, forest edges, and agricultural areas with scattered trees.",
"song": "Loud, harsh calls similar to other chachalacas, often given by groups in noisy choruses at dawn and dusk.",
"range": "Honduras through Central America to northern Colombia.",
"fun_fact": "Chachalacas get their name from the sound of their call - cha-cha-lac-a - repeated over and over.",
},
"Band-tailed Guan": {
"habitat": "Humid mountain forests and cloud forests.",
"song": "A series of deep, resonant honking sounds, especially vocal during the breeding season.",
"range": "Andes from Colombia and Venezuela south to Bolivia.",
"fun_fact": "Band-tailed Guans travel in small family groups and are surprisingly acrobatic for their size, leaping between branches to reach fruit.",
},
"Black-capped Tinamou": {
"habitat": "Forests from lowlands to lower montane elevations.",
"song": "A bubbling, accelerating series of whistles - sounds like a bouncing ball slowing to a stop, but in reverse.",
"range": "Central Peru to Bolivia, in the eastern Andean slopes.",
"fun_fact": "Like other tinamous, the Black-capped Tinamou can fly but strongly prefers to walk. When it does fly, it's in short, explosive bursts.",
},
"Spotted Nothura": {
"habitat": "Grasslands and open areas, including agricultural fields and pastures.",
"song": "A series of sharp, staccato whistles, often given from the ground in open grassland.",
"range": "Central South America - Brazil, Paraguay, Argentina, Uruguay.",
"fun_fact": "Nothuras are grassland tinamous - unlike their forest-dwelling relatives, they live in open habitats and look somewhat like partridges.",
},
"Red-winged Tinamou": {
"habitat": "Grasslands, scrublands, and agricultural areas in southern South America.",
"song": "A melodious, flute-like whistle that rises and falls, often heard at dawn and dusk across the pampas.",
"range": "Southern Brazil, Paraguay, Uruguay, Argentina.",
"fun_fact": "Named for the rufous-red color visible on its wings in flight - one of the few times you'll see this secretive bird in the open.",
},
"Australian Brushturkey": {
"habitat": "Rainforests, scrublands, and suburban gardens in eastern Australia.",
"song": "Deep booming calls during breeding. Otherwise relatively quiet compared to other species in this list.",
"range": "Eastern Australia, from Cape York to southern New South Wales.",
"fun_fact": "Males build enormous mound nests (up to 4 meters wide) out of decomposing vegetation. The heat from decomposition incubates the eggs - no body heat required.",
},
"Dusky Megapode": {
"habitat": "Tropical forests on islands in the western Pacific, often near volcanic areas.",
"song": "Loud wailing calls, especially at night. Some species in this family are among the noisiest birds in their habitat.",
"range": "Islands of Indonesia and Papua New Guinea.",
"fun_fact": "Some megapodes use volcanic heat to incubate their eggs, burying them in volcanically warmed soil - the only birds known to use geothermal energy for reproduction.",
},
"Tataupa Tinamou": {
"habitat": "Forest edges, secondary growth, and dense undergrowth in tropical and subtropical regions.",
"song": "A rich, mellow series of whistles. Has been described as one of the most beautiful bird songs in South America.",
"range": "Eastern South America from Brazil to Argentina.",
"fun_fact": "The Tataupa Tinamou is more tolerant of disturbed habitats than many of its relatives, which helps it survive in areas affected by deforestation.",
},
}
ALL_SPECIES = sorted(set(classifier.model.config.id2label.values()))
# Sighting log (in-memory)
sighting_log = []
def classify_bird(audio):
if audio is None:
return "Please upload or record an audio file.", gr.update(), gr.update()
sr, y = audio
if y.dtype == np.int16:
y = y.astype(np.float32) / 32768.0
elif y.dtype == np.int32:
y = y.astype(np.float32) / 2147483648.0
elif y.dtype != np.float32:
y = y.astype(np.float32)
if len(y.shape) > 1:
y = y[:, 0]
if sr != 16000:
duration = len(y) / sr
new_length = int(duration * 16000)
y = np.interp(
np.linspace(0, len(y) - 1, new_length),
np.arange(len(y)),
y,
)
sr = 16000
results = classifier({"sampling_rate": sr, "raw": y}, top_k=3)
lines = []
top_species = results[0]["label"]
top_score = results[0]["score"]
if top_score < 0.40:
lines.append("Not confident - this may not be a recognizable bird song,")
lines.append("or the species may not be in this model's training data.\n")
for i, pred in enumerate(results, 1):
score = pred["score"]
label = pred["label"]
# Color-coded confidence
if score >= 0.70:
indicator = "HIGH"
elif score >= 0.40:
indicator = "MED"
else:
indicator = "LOW"
bar_length = int(score * 20)
bar = "#" * bar_length + "." * (20 - bar_length)
lines.append(f"[{indicator}] {i}. {label}")
lines.append(f" {bar} {score:.1%}\n")
return "\n".join(lines), gr.update(value=top_species), gr.update()
def get_bird_info(species):
if species in BIRD_INFO:
info = BIRD_INFO[species]
text = f"## {species}\n\n"
text += f"**Habitat:** {info['habitat']}\n\n"
text += f"**Song:** {info['song']}\n\n"
text += f"**Range:** {info['range']}\n\n"
text += f"**Fun fact:** {info['fun_fact']}"
return text
else:
return (
f"## {species}\n\n"
f"No detailed description available for this species yet. "
f"I've written descriptions for 15 of the 50 species in this model. "
f"Try searching [Xeno-Canto](https://xeno-canto.org/) or the "
f"[Cornell Lab](https://www.allaboutbirds.org/) for more information."
)
def add_sighting(species, location, notes):
if not species:
return format_log()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
entry = {
"species": species,
"date": timestamp,
"location": location or "Not specified",
"notes": notes or "",
}
sighting_log.append(entry)
return format_log()
def format_log():
if not sighting_log:
return "No sightings logged yet. Identify a bird and add it to your log!"
lines = [f"### Sighting Log ({len(sighting_log)} entries)\n"]
for i, entry in enumerate(sighting_log, 1):
lines.append(f"**{i}. {entry['species']}**")
lines.append(f" {entry['date']} | {entry['location']}")
if entry["notes"]:
lines.append(f" Notes: {entry['notes']}")
lines.append("")
lines.append("---")
lines.append(
"*This log is stored in memory and will reset when the Space restarts. "
"Copy your log if you want to save it!*"
)
return "\n".join(lines)
# Build the interface with tabs
with gr.Blocks(theme=gr.themes.Soft(), title="The Backyard Birder") as demo:
gr.Markdown(
"""
# The Backyard Birder
A multi-feature birding assistant. Identify birds from audio recordings,
learn about the species, and keep a sighting log.
**Model:** `dima806/bird_sounds_classification` - 50 species (Tinamous, Guans, Chachalacas, and relatives).
These are neotropical birds, not typical North American backyard species. The tool demonstrates how
audio classification pipelines work; with a different model (like BirdNET), it could identify local birds too.
---
"""
)
# State for passing species between tabs
current_species = gr.State("")
with gr.Tabs():
# Tab 1: Identify
with gr.Tab("Identify"):
gr.Markdown("Upload a bird recording to identify the species. Best results with clean recordings of 3+ seconds.")
with gr.Row():
with gr.Column():
audio_input = gr.Audio(
label="Upload or Record Audio",
type="numpy",
)
classify_btn = gr.Button("Identify Bird", variant="primary")
with gr.Column():
classification_output = gr.Textbox(
label="Top 3 Predictions",
lines=10,
interactive=False,
)
species_display = gr.Textbox(
label="Top prediction",
visible=False,
)
# Tab 2: Learn
with gr.Tab("Learn"):
gr.Markdown("Select a species to learn about it. Descriptions available for 15 of the 50 species.")
species_dropdown = gr.Dropdown(
choices=ALL_SPECIES,
label="Select a Species",
value="Great Tinamou",
)
bird_info_output = gr.Markdown(
value=get_bird_info("Great Tinamou"),
)
# Tab 3: Log
with gr.Tab("Log Sightings"):
gr.Markdown("Keep track of what you hear. Add species to your sighting log with location and notes.")
with gr.Row():
with gr.Column():
log_species = gr.Dropdown(
choices=ALL_SPECIES,
label="Species",
allow_custom_value=True,
)
log_location = gr.Textbox(
label="Location",
placeholder="e.g., Backyard, Local park, Trail near school...",
)
log_notes = gr.Textbox(
label="Notes",
placeholder="e.g., Heard at dawn, two birds calling back and forth...",
lines=2,
)
log_btn = gr.Button("Add to Log", variant="primary")
with gr.Column():
log_output = gr.Markdown(value=format_log())
# Wire up events
classify_btn.click(
fn=classify_bird,
inputs=[audio_input],
outputs=[classification_output, species_dropdown, species_display],
)
species_dropdown.change(
fn=get_bird_info,
inputs=[species_dropdown],
outputs=[bird_info_output],
)
log_btn.click(
fn=add_sighting,
inputs=[log_species, log_location, log_notes],
outputs=[log_output],
)
gr.Markdown(
"""
---
*Riley's Space 3 - AI + Research Level 2*
**How this works:** The Identify tab uses an audio classification model to predict which species
is singing. The Learn tab shows hand-written descriptions for 15 species. The Log tab lets you
track your sightings during this session. This is a multi-model pipeline: audio classification
feeds species information, and errors in identification propagate to wrong descriptions.
"""
)
demo.launch() |