Skip to content

Commit 56d90ce

Browse files
authored
Merge pull request #11 from MutilatedPeripherals/packaging-experiment
Update file structure to make it into a package
2 parents d7b44d5 + 4bae458 commit 56d90ce

15 files changed

Lines changed: 106 additions & 60 deletions

.github/workflows/run-tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@ jobs:
3535
pip install -r requirements.txt
3636
pip install pytest
3737
38+
- name: Install package
39+
run: pip install -e .
40+
3841
- name: Run tests
3942
run: pytest .

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ venv
66
*.pkl
77
output/*
88
download_cache.json
9-
*.csv
9+
*.csv
10+
dist

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 MutilatedPeripherals
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Blast beat counter
1+
# Blast beat detector
22

33
[![Tests](https://github.com/MutilatedPeripherals/blastbeat-counter/actions/workflows/run-tests.yml/badge.svg)](https://github.com/MutilatedPeripherals/blastbeat-counter/actions/workflows/run-tests.yml)
44

@@ -38,15 +38,18 @@ And here is another one, from the ecuadorian band Curetaje:
3838

3939
## Demo
4040

41-
Currently the detector is not deployed as a service because demucs requires a GPU for drum-track separation in reasonable time, and those servers aren't free...
41+
Currently the detector is not deployed as a service because demucs requires a GPU for drum-track separation in
42+
reasonable time, and those servers aren't free...
4243

4344
But you can:
44-
- Try this notebook to process some songs using Google's free-tier GPUs: <a target="_blank" href="https://colab.research.google.com/drive/1s3fcIpFAnJWguS2-sE6LKjWVkQlOpZK1?usp=sharing">
45+
46+
- Try this notebook to process some songs using Google's free-tier
47+
GPUs: <a target="_blank" href="https://colab.research.google.com/drive/1s3fcIpFAnJWguS2-sE6LKjWVkQlOpZK1?usp=sharing">
4548
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
46-
</a>
49+
</a>
4750

4851
- Or just directly download examples of processed songs
49-
from [here](https://drive.google.com/drive/folders/1YFoxrsrBo8hl0cOYkdxCsfW_bf3CX7Al)
52+
from [here](https://drive.google.com/drive/folders/1YFoxrsrBo8hl0cOYkdxCsfW_bf3CX7Al)
5053

5154
And then upload the results to the [visualizer](https://mutilatedperipherals.github.io/blastbeat-counter/):
5255

@@ -70,25 +73,26 @@ apt-get install ffmpeg
7073

7174
### Specify the input files & run the code
7275

73-
1. Create a `csv` file to pass as input to the `pipeline.py` file.
76+
1. Create a `csv` file to pass as input to the `pipeline.py` file.
7477

75-
The only mandatory column is `src`, with the file paths of the songs to analyze. Youtube URLs are also supported on a best-effort basis (uses `yt-dlp` to download the audio).
78+
The only mandatory column is `src`, with the file paths of the songs to analyze. Youtube URLs are also supported on a
79+
best-effort basis (uses `yt-dlp` to download the audio).
7680

77-
Example:
81+
Example:
7882

7983
```csv
8084
src
8185
/home/linomp/Downloads/CURETAJE - Arutam.mp3
8286
https://youtu.be/dQw4w9WgXcQ?si=J-UoAhM54KQGR6eW
8387
```
84-
88+
8589
<details>
8690
<summary>Additional fields (advanced)</summary>
8791
Other fields are supported for debugging & development, with the most important one being `step_size_in_seconds`, which determines the size of the segments on which the song is split & analized (default value: 0.15s).
88-
89-
In `pipeline.py` you can see all the configurable fields. If left blank or unspecified, defaults will be used.
9092
91-
Here is an example specifying an extra field:
93+
In `pipeline.py` you can see all the configurable fields. If left blank or unspecified, defaults will be used.
94+
95+
Here is an example specifying an extra field:
9296
9397
```csv
9498
src,step_size_in_seconds

index.html

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,30 @@ <h2>BlastViz</h2>
3636
<h4>Blastbeat Detection Visualizer</h4>
3737
<div id="explainer">
3838
<hr>
39-
<p><i><strong>Warning:</strong> This is a work in progress. The visualizer expects a ZIP file containing an audio
39+
<p><i><strong>Warning:</strong> This is not a stand-alone tool. The visualizer expects a ZIP file containing an
40+
audio
4041
file (MP3 or WAV), a JSON file with the identified blast-beat sections, and optionally a drum-only audio track.</i>
4142
</p>
42-
<p>Expected JSON structure:</p>
43+
<p><i>Expected JSON structure:</i></p>
4344
<pre>
4445
{
4546
"blast_beats": [
4647
{"start_time": 12.5, "end_time": 15.0},
47-
{"start_time": 30.0, "end_time": 32.5}
48+
{"start_time": 30.0, "end_time": 32.5},
49+
...
4850
]
4951
}
5052
</pre>
51-
<p>You can download some examples from <a
53+
<p>Try this notebook to process some songs using Google's free-tier
54+
GPUs: <a target="_blank"
55+
href="https://colab.research.google.com/drive/1s3fcIpFAnJWguS2-sE6LKjWVkQlOpZK1?usp=sharing">
56+
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
57+
</a>
58+
</p>
59+
<p>Or directly download some processed song examples from <a
5260
href="https://drive.google.com/drive/folders/1YFoxrsrBo8hl0cOYkdxCsfW_bf3CX7Al?usp=drive_link"
53-
target="_blank">this Google Drive folder</a></p>
61+
target="_blank">this Google Drive folder</a>
62+
</p>
5463
</div>
5564
<div class="load-control">
5665
<input type="file" id="zipInput" accept=".zip">

pyproject.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[build-system]
2+
requires = ["hatchling >= 1.26"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "blastbeat_detector"
7+
version = "0.0.6"
8+
authors = [
9+
{ name = "@linomp" },
10+
{ name = "@lmeullibre" },
11+
{ name = "@m-poh" },
12+
]
13+
description = "Experimental package for identifying blast-beats in songs using spectral analysis"
14+
readme = "README.md"
15+
requires-python = ">=3.9"
16+
license = "MIT"
17+
license-files = ["LICEN[CS]E*"]
18+
19+
[project.urls]
20+
Repository = "https://github.com/MutilatedPeripherals/blastbeat-detector"

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ matplotlib==3.10.3
44
numpy==1.26.4
55
pytest==8.4.1
66
yt-dlp==2025.11.12
7-
pydub==0.25.1
7+
pydub==0.25.1
8+
torchcodec==0.8.1
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55

66
from yt_dlp import YoutubeDL
77

8-
CACHE_FILE = Path(__file__).parent / "download_cache.json"
9-
108

119
def download_from_youtube_as_mp3(url: str) -> tuple[bool, Path | None]:
1210
if not re.match(r"(https?://)?(www\.)?(youtube\.com|youtu\.be)/", url):
1311
raise ValueError("The provided URL is not a valid YouTube video URL.")
1412

15-
if CACHE_FILE.exists():
16-
with open(CACHE_FILE, "r") as f:
13+
cache_file = Path.cwd().resolve() / "download_cache.json"
14+
if cache_file.exists():
15+
with open(cache_file, "r") as f:
1716
cache = json.load(f)
1817
if url in cache:
1918
cached_path = Path(cache[url])
@@ -23,7 +22,7 @@ def download_from_youtube_as_mp3(url: str) -> tuple[bool, Path | None]:
2322
else:
2423
cache = {}
2524

26-
output_folder = Path(__file__).parent / "tmp"
25+
output_folder = Path.cwd().resolve() / "tmp"
2726
output_folder.mkdir(exist_ok=True)
2827

2928
temp_name = str(uuid.uuid4())
@@ -55,7 +54,7 @@ def download_from_youtube_as_mp3(url: str) -> tuple[bool, Path | None]:
5554
downloaded_path.rename(final_path)
5655

5756
cache[url] = str(final_path)
58-
with open(CACHE_FILE, "w") as f:
57+
with open(cache_file, "w") as f:
5958
json.dump(cache, f, indent=2)
6059

6160
return True, final_path
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
"ignore",
1616
message=".*this function's implementation will be changed to use torchaudio.save_with_torchcodec.*",
1717
)
18-
18+
warnings.filterwarnings(
19+
"ignore",
20+
message=".*The 'encoding' parameter is not fully supported by TorchCodec AudioEncoder.*",
21+
)
1922

2023
def read_audio_file(input_file_path: Path) -> tuple[np.ndarray, np.ndarray, float]:
2124
y, sample_rate = librosa.load(input_file_path, mono=True)
@@ -44,7 +47,7 @@ def extract_drums(
4447
)
4548

4649
if skip_cache or not extracted_drums_file_path.exists():
47-
print("Extracting drums")
50+
print(f"Separating drum track from \'{input_file_path}\'")
4851
temp_file_path = (
4952
input_file_path.parent
5053
/ "htdemucs"
@@ -71,7 +74,7 @@ def extract_drums(
7174

7275

7376
if __name__ == "__main__":
74-
base_dir = "/home/linomp/Downloads"
77+
base_dir = Path.cwd().resolve()
7578

7679
file_path = Path(f"{base_dir}/Dying Fetus - Subjected To A Beating.wav")
7780
extract_drums(file_path)

0 commit comments

Comments
 (0)