profplate commited on
Commit
b3dff30
·
verified ·
1 Parent(s): e7c2386

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -0
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+ import numpy as np
4
+
5
+ classifier = pipeline(
6
+ "audio-classification",
7
+ model="dima806/bird_sounds_classification",
8
+ device=-1,
9
+ )
10
+
11
+ # Get the full species list from the model config
12
+ SPECIES_LIST = sorted(set(
13
+ classifier.model.config.id2label.values()
14
+ ))
15
+
16
+ def classify_bird(audio):
17
+ if audio is None:
18
+ return "Please upload or record an audio file."
19
+
20
+ sr, y = audio
21
+
22
+ # Convert to float32 and normalize
23
+ if y.dtype == np.int16:
24
+ y = y.astype(np.float32) / 32768.0
25
+ elif y.dtype == np.int32:
26
+ y = y.astype(np.float32) / 2147483648.0
27
+ elif y.dtype != np.float32:
28
+ y = y.astype(np.float32)
29
+
30
+ # If stereo, take first channel
31
+ if len(y.shape) > 1:
32
+ y = y[:, 0]
33
+
34
+ # Resample to 16kHz if needed (model expects 16kHz)
35
+ if sr != 16000:
36
+ # Simple resampling using numpy interpolation
37
+ duration = len(y) / sr
38
+ new_length = int(duration * 16000)
39
+ y = np.interp(
40
+ np.linspace(0, len(y) - 1, new_length),
41
+ np.arange(len(y)),
42
+ y,
43
+ )
44
+ sr = 16000
45
+
46
+ results = classifier({"sampling_rate": sr, "raw": y}, top_k=5)
47
+
48
+ # Format output
49
+ lines = []
50
+ for i, pred in enumerate(results, 1):
51
+ score = pred["score"]
52
+ label = pred["label"]
53
+
54
+ if i == 1 and score < 0.40:
55
+ lines.append("Not confident - this may not be a recognizable bird song,")
56
+ lines.append("or the species may not be in this model's training data.")
57
+ lines.append(f"Best guess: {label} ({score:.0%})")
58
+ lines.append("")
59
+ lines.append("Top 5 predictions:")
60
+ lines.append(f" 1. {label} - {score:.1%}")
61
+ continue
62
+
63
+ bar_length = int(score * 20)
64
+ bar = "#" * bar_length + "." * (20 - bar_length)
65
+ lines.append(f"{i}. {label}")
66
+ lines.append(f" {bar} {score:.1%}")
67
+
68
+ return "\n".join(lines)
69
+
70
+
71
+ demo = gr.Interface(
72
+ fn=classify_bird,
73
+ inputs=gr.Audio(
74
+ label="Upload or Record a Bird Song",
75
+ type="numpy",
76
+ ),
77
+ outputs=gr.Textbox(label="Classification Results", lines=12),
78
+ title="Bird Song Classifier",
79
+ description=(
80
+ "Upload a bird song recording and this model will try to identify the species. "
81
+ "Uses dima806/bird_sounds_classification, a wav2vec2-based classifier trained on "
82
+ "50 bird species (mostly Tinamous, Guans, and Chachalacas - neotropical birds). "
83
+ "Best results with clean recordings of 3+ seconds.\n\n"
84
+ "Note: This model was trained on tropical/neotropical species. "
85
+ "It won't recognize common North American backyard birds like cardinals or robins. "
86
+ "That's a training data limitation, not an architecture limitation.\n\n"
87
+ "Try recordings from Xeno-Canto (https://xeno-canto.org/) - search for species like "
88
+ "Great Tinamou, Plain Chachalaca, or Crested Guan."
89
+ ),
90
+ article=(
91
+ "### Species this model knows\n\n"
92
+ + ", ".join(SPECIES_LIST)
93
+ + "\n\n---\n*Riley's Space 2 - AI + Research Level 2*"
94
+ ),
95
+ theme=gr.themes.Soft(),
96
+ allow_flagging="never",
97
+ )
98
+
99
+ demo.launch()