Spaces:
Sleeping
Sleeping
Bohdan Laskavyi commited on
Commit Β·
ec00d29
1
Parent(s): e505a8d
front final update
Browse files
README.md
CHANGED
|
@@ -84,6 +84,28 @@ Ai-sounds-detection/
|
|
| 84 |
βββ MLtraining/ # Machine learning training notebooks and scripts
|
| 85 |
```
|
| 86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
## File Documentation
|
| 88 |
|
| 89 |
### main.py
|
|
|
|
| 84 |
βββ MLtraining/ # Machine learning training notebooks and scripts
|
| 85 |
```
|
| 86 |
|
| 87 |
+
## Dataset preparation
|
| 88 |
+
|
| 89 |
+
The `data/` folder is organized by sound category and is used to store training and validation clips.
|
| 90 |
+
- `drilling/`, `vacuum/`, `keyboard/`, `washing/` contain labeled audio clips.
|
| 91 |
+
- Use `model/cutter.py` to split long recordings into fixed-length segments.
|
| 92 |
+
- Use `model/cleaner.py` to clean and filter audio samples.
|
| 93 |
+
- Use `model/dataset_into_hf.py` to upload the prepared dataset to HuggingFace if needed.
|
| 94 |
+
|
| 95 |
+
## Reproduce the model
|
| 96 |
+
|
| 97 |
+
The app loads the pre-trained model from HuggingFace Hub:
|
| 98 |
+
- Dataset: `https://huggingface.co/datasets/kadzioriron/Sounds`
|
| 99 |
+
- Model: `https://huggingface.co/kadzioriron/Sounds-CNN`
|
| 100 |
+
|
| 101 |
+
To reproduce the app locally:
|
| 102 |
+
```bash
|
| 103 |
+
pip install -r requirements.txt
|
| 104 |
+
streamlit run main.py
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
To retrain or prepare new audio data, use the utility scripts in `model/` and the feature extraction functions in `utilits.py`.
|
| 108 |
+
|
| 109 |
## File Documentation
|
| 110 |
|
| 111 |
### main.py
|
main.py
CHANGED
|
@@ -7,58 +7,114 @@ from huggingface_hub import hf_hub_download
|
|
| 7 |
# classes
|
| 8 |
CLASSES = ["drilling", "vacuum", "keyboard", "washing"]
|
| 9 |
|
| 10 |
-
#
|
| 11 |
@st.cache_resource
|
| 12 |
def load_ai_model():
|
| 13 |
-
|
| 14 |
-
REPO_ID = "kadzioriron/Sounds-CNN"
|
| 15 |
-
|
| 16 |
model_path = hf_hub_download(repo_id=REPO_ID, filename="ai_sounds_model.keras")
|
| 17 |
-
|
| 18 |
return tf.keras.models.load_model(model_path)
|
| 19 |
|
| 20 |
model = load_ai_model()
|
| 21 |
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
st.title("AI Sounds Detection")
|
| 24 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
-
|
| 27 |
-
uploaded_file = st.file_uploader("Choose the type of the file", type=['wav', 'mp3'])
|
| 28 |
|
| 29 |
if uploaded_file is not None:
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
st.write("Reading your file and predicting...")
|
| 34 |
-
|
| 35 |
-
# Get data using our utils function
|
| 36 |
y, sr = get_audio_data(uploaded_file)
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
st.success(f"π€ AI Prediction: **{CLASSES[predicted_index].upper()}**")
|
| 48 |
st.info(f"Confidence: {confidence:.2f}%")
|
|
|
|
| 49 |
st.divider()
|
| 50 |
-
|
| 51 |
-
""
|
|
|
|
|
|
|
|
|
|
| 52 |
st.subheader("Waveform")
|
| 53 |
-
st.write("
|
| 54 |
fig_wave = plot_waveform(y, sr)
|
| 55 |
-
st.pyplot(fig_wave)
|
| 56 |
-
|
| 57 |
st.subheader("Mel-spectrogram")
|
| 58 |
-
st.write("
|
| 59 |
fig_mel = plot_mel_spectrogram(y, sr)
|
| 60 |
-
st.pyplot(fig_mel)
|
| 61 |
|
| 62 |
-
st.subheader("Sample rates")
|
| 63 |
-
st.write("Shows the sample rates of the audio file")
|
| 64 |
-
st.write(f"Sample rate: {sr} Hz")
|
|
|
|
| 7 |
# classes
|
| 8 |
CLASSES = ["drilling", "vacuum", "keyboard", "washing"]
|
| 9 |
|
| 10 |
+
# AI model loader
|
| 11 |
@st.cache_resource
|
| 12 |
def load_ai_model():
|
| 13 |
+
REPO_ID = "kadzioriron/Sounds-CNN"
|
|
|
|
|
|
|
| 14 |
model_path = hf_hub_download(repo_id=REPO_ID, filename="ai_sounds_model.keras")
|
|
|
|
| 15 |
return tf.keras.models.load_model(model_path)
|
| 16 |
|
| 17 |
model = load_ai_model()
|
| 18 |
|
| 19 |
+
st.set_page_config(
|
| 20 |
+
page_title="AI Sounds Detection",
|
| 21 |
+
page_icon="π",
|
| 22 |
+
layout="wide",
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
st.title("AI Sounds Detection")
|
| 26 |
+
st.markdown(
|
| 27 |
+
"This app detects common household sounds and displays audio visualizations before it predicts the sound category. Upload a short `.wav` or `.mp3` clip and the AI model will classify it as one of the supported sounds."
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
st.subheader("How this works")
|
| 31 |
+
st.markdown(
|
| 32 |
+
"- The app loads a pre-trained AI model from HuggingFace Hub.\n"
|
| 33 |
+
"- It converts your audio into features the model was trained on, including MFCCs and mel-spectrogram data.\n"
|
| 34 |
+
"- The model then predicts the most likely sound category and shows confidence."
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
st.subheader("About the model")
|
| 38 |
+
st.markdown(
|
| 39 |
+
"- Pre-trained convolutional neural network (CNN) for sound classification.\n"
|
| 40 |
+
"- Uses MFCC and mel-spectrogram features extracted from audio.\n"
|
| 41 |
+
"- Trained on labeled household sound clips from the HuggingFace Sounds dataset."
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
st.subheader("Supported sound categories")
|
| 45 |
+
st.markdown(
|
| 46 |
+
"The model currently recognizes these sounds:"
|
| 47 |
+
)
|
| 48 |
+
st.write("- **Drilling** β electric drill or similar tool noise")
|
| 49 |
+
st.write("- **Vacuum** β vacuum cleaner motor or suction noise")
|
| 50 |
+
st.write("- **Keyboard** β typing and key press sounds")
|
| 51 |
+
st.write("- **Washing** β washing machine cycle or spin noise")
|
| 52 |
+
|
| 53 |
+
st.subheader("Upload instructions")
|
| 54 |
+
st.markdown(
|
| 55 |
+
"- Use a clear audio file with minimal background noise.\n"
|
| 56 |
+
"- Best results come from short recordings (2β10 seconds).\n"
|
| 57 |
+
"- Supported file formats: `.wav`, `.mp3`.\n"
|
| 58 |
+
"- The file should contain one primary sound category at a time."
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
with st.sidebar:
|
| 62 |
+
st.header("Resources")
|
| 63 |
+
st.markdown(
|
| 64 |
+
"- [HuggingFace Dataset](https://huggingface.co/datasets/kadzioriron/Sounds)\n"
|
| 65 |
+
"- [HuggingFace Model](https://huggingface.co/kadzioriron/Sounds-CNN)\n"
|
| 66 |
+
"- [Live Demo Space](https://huggingface.co/spaces/kadzioriron/AI_Sounds_detection)\n"
|
| 67 |
+
)
|
| 68 |
+
st.markdown("---")
|
| 69 |
+
st.header("Quick tips")
|
| 70 |
+
st.write("- Upload a single sound type per file.")
|
| 71 |
+
st.write("- Use a quiet room and hold the recording device near the sound source.")
|
| 72 |
+
st.write("- Avoid music or multiple devices running at once.")
|
| 73 |
|
| 74 |
+
uploaded_file = st.file_uploader("Upload your sound file", type=["wav", "mp3"])
|
|
|
|
| 75 |
|
| 76 |
if uploaded_file is not None:
|
| 77 |
+
st.audio(uploaded_file, format="audio/wav")
|
| 78 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
y, sr = get_audio_data(uploaded_file)
|
| 80 |
+
duration = len(y) / sr if sr > 0 else 0
|
| 81 |
+
file_size_kb = uploaded_file.size / 1024 if hasattr(uploaded_file, "size") else None
|
| 82 |
+
|
| 83 |
+
st.subheader("File details")
|
| 84 |
+
st.write(f"**Name:** {uploaded_file.name}")
|
| 85 |
+
if file_size_kb is not None:
|
| 86 |
+
st.write(f"**Size:** {file_size_kb:.1f} KB")
|
| 87 |
+
st.write(f"**Duration:** {duration:.2f} seconds")
|
| 88 |
+
st.write(f"**Sample rate:** {sr} Hz")
|
| 89 |
+
|
| 90 |
+
with st.spinner("Extracting features and predicting..."):
|
| 91 |
+
processed_audio = prepare_audio_for_model(y, sr)
|
| 92 |
+
predictions = model.predict(processed_audio)
|
| 93 |
+
|
| 94 |
+
top_predictions = sorted(
|
| 95 |
+
[(CLASSES[i], float(predictions[0][i]) * 100) for i in range(len(CLASSES))],
|
| 96 |
+
key=lambda x: x[1],
|
| 97 |
+
reverse=True,
|
| 98 |
+
)[:3]
|
| 99 |
+
predicted_index = np.argmax(predictions[0])
|
| 100 |
+
confidence = float(predictions[0][predicted_index]) * 100
|
| 101 |
+
|
| 102 |
st.success(f"π€ AI Prediction: **{CLASSES[predicted_index].upper()}**")
|
| 103 |
st.info(f"Confidence: {confidence:.2f}%")
|
| 104 |
+
st.caption("Higher confidence means the sound matches the trained category more clearly.")
|
| 105 |
st.divider()
|
| 106 |
+
|
| 107 |
+
st.subheader("Top 3 predictions")
|
| 108 |
+
for label, score in top_predictions:
|
| 109 |
+
st.write(f"- **{label}**: {score:.1f}%")
|
| 110 |
+
|
| 111 |
st.subheader("Waveform")
|
| 112 |
+
st.write("The waveform shows amplitude over time and helps you inspect the sound structure.")
|
| 113 |
fig_wave = plot_waveform(y, sr)
|
| 114 |
+
st.pyplot(fig_wave)
|
| 115 |
+
|
| 116 |
st.subheader("Mel-spectrogram")
|
| 117 |
+
st.write("The mel-spectrogram is what the AI model uses to recognize sound patterns.")
|
| 118 |
fig_mel = plot_mel_spectrogram(y, sr)
|
| 119 |
+
st.pyplot(fig_mel)
|
| 120 |
|
|
|
|
|
|
|
|
|