Spaces:
Sleeping
Sleeping
Commit
·
083c84b
1
Parent(s):
2836474
Script fixes
Browse files
app.py
CHANGED
@@ -316,32 +316,31 @@ def smooth_predictions(data: np.ndarray) -> np.ndarray:
|
|
316 |
|
317 |
return smoothed_data
|
318 |
|
|
|
|
|
|
|
|
|
319 |
def make_predictions(model, processed_audio, audio_features, url, video_name):
|
320 |
predictions = model.predict(processed_audio)[0]
|
321 |
-
binary_predictions = np.round(
|
322 |
-
predictions[:(len(audio_features.meter_grid) - 1)]).flatten()
|
323 |
smoothed_predictions = smooth_predictions(binary_predictions)
|
324 |
|
325 |
-
meter_grid_times = librosa.frames_to_time(
|
326 |
-
|
327 |
-
|
328 |
-
smoothed_predictions)) if smoothed_predictions[i] == 1 and (i == 0 or smoothed_predictions[i - 1] == 0)]
|
329 |
-
chorus_end_times = [meter_grid_times[i + 1] for i in range(len(
|
330 |
-
smoothed_predictions)) if smoothed_predictions[i] == 1 and (i == len(smoothed_predictions) - 1 or smoothed_predictions[i + 1] == 0)]
|
331 |
|
332 |
st.write(f"**Video Title:** {video_name}")
|
333 |
st.write(f"**Number of choruses identified:** {len(chorus_start_times)}")
|
334 |
|
335 |
for start_time, end_time in zip(chorus_start_times, chorus_end_times):
|
336 |
link = f"{url}&t={int(start_time)}s"
|
337 |
-
st.write(f"Chorus from {start_time
|
338 |
|
339 |
if len(chorus_start_times) == 0:
|
340 |
st.write("No choruses identified.")
|
341 |
|
342 |
return smoothed_predictions
|
343 |
|
344 |
-
|
345 |
def plot_meter_lines(ax: plt.Axes, meter_grid_times: np.ndarray) -> None:
|
346 |
for time in meter_grid_times:
|
347 |
ax.axvline(x=time, color='grey', linestyle='--',
|
@@ -393,15 +392,16 @@ def plot_predictions(audio_features, predictions):
|
|
393 |
|
394 |
|
395 |
def main():
|
396 |
-
st.title("Chorus
|
|
|
397 |
st.write("Upload a YouTube URL to find the chorus in the song.")
|
398 |
url = st.text_input("YouTube URL")
|
399 |
if st.button("Find Chorus"):
|
400 |
if url:
|
401 |
-
with st.spinner('
|
402 |
audio_file, video_title, temp_dir = extract_audio(url)
|
403 |
if audio_file:
|
404 |
-
with st.spinner('
|
405 |
strip_silence(audio_file)
|
406 |
with st.spinner('Processing audio...'):
|
407 |
processed_audio, audio_features = process_audio(audio_path=audio_file)
|
@@ -416,4 +416,4 @@ def main():
|
|
416 |
st.error("Please enter a valid YouTube URL")
|
417 |
|
418 |
if __name__ == "__main__":
|
419 |
-
main()
|
|
|
316 |
|
317 |
return smoothed_data
|
318 |
|
319 |
+
def format_time(seconds):
|
320 |
+
m, s = divmod(seconds, 60)
|
321 |
+
return f"{int(m)}:{s:05.2f}"
|
322 |
+
|
323 |
def make_predictions(model, processed_audio, audio_features, url, video_name):
|
324 |
predictions = model.predict(processed_audio)[0]
|
325 |
+
binary_predictions = np.round(predictions[:(len(audio_features.meter_grid) - 1)]).flatten()
|
|
|
326 |
smoothed_predictions = smooth_predictions(binary_predictions)
|
327 |
|
328 |
+
meter_grid_times = librosa.frames_to_time(audio_features.meter_grid, sr=audio_features.sr, hop_length=audio_features.hop_length)
|
329 |
+
chorus_start_times = [meter_grid_times[i] for i in range(len(smoothed_predictions)) if smoothed_predictions[i] == 1 and (i == 0 or smoothed_predictions[i - 1] == 0)]
|
330 |
+
chorus_end_times = [meter_grid_times[i + 1] for i in range(len(smoothed_predictions)) if smoothed_predictions[i] == 1 and (i == len(smoothed_predictions) - 1 or smoothed_predictions[i + 1] == 0)]
|
|
|
|
|
|
|
331 |
|
332 |
st.write(f"**Video Title:** {video_name}")
|
333 |
st.write(f"**Number of choruses identified:** {len(chorus_start_times)}")
|
334 |
|
335 |
for start_time, end_time in zip(chorus_start_times, chorus_end_times):
|
336 |
link = f"{url}&t={int(start_time)}s"
|
337 |
+
st.write(f"Chorus from {format_time(start_time)} to {format_time(end_time)}: [{link}]({link})")
|
338 |
|
339 |
if len(chorus_start_times) == 0:
|
340 |
st.write("No choruses identified.")
|
341 |
|
342 |
return smoothed_predictions
|
343 |
|
|
|
344 |
def plot_meter_lines(ax: plt.Axes, meter_grid_times: np.ndarray) -> None:
|
345 |
for time in meter_grid_times:
|
346 |
ax.axvline(x=time, color='grey', linestyle='--',
|
|
|
392 |
|
393 |
|
394 |
def main():
|
395 |
+
st.title("Chorus Finder")
|
396 |
+
st.write("This app uses a pre-trained convolutional recurrent neural network to predict chorus locations in music. To learn more about this project, visit [github.com/dennisvdang/chorus-detection](https://github.com/dennisvdang/chorus-detection).")
|
397 |
st.write("Upload a YouTube URL to find the chorus in the song.")
|
398 |
url = st.text_input("YouTube URL")
|
399 |
if st.button("Find Chorus"):
|
400 |
if url:
|
401 |
+
with st.spinner('Analyzing YouTube link...'):
|
402 |
audio_file, video_title, temp_dir = extract_audio(url)
|
403 |
if audio_file:
|
404 |
+
with st.spinner('Trimming silence...'):
|
405 |
strip_silence(audio_file)
|
406 |
with st.spinner('Processing audio...'):
|
407 |
processed_audio, audio_features = process_audio(audio_path=audio_file)
|
|
|
416 |
st.error("Please enter a valid YouTube URL")
|
417 |
|
418 |
if __name__ == "__main__":
|
419 |
+
main()
|
style.css
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
body {
|
2 |
+
/* background-image: url('https://your-image-url.com/background.jpg'); */
|
3 |
+
background-size: cover;
|
4 |
+
}
|
5 |
+
|
6 |
+
.stButton>button {
|
7 |
+
background-color: #fcb900;
|
8 |
+
color: white;
|
9 |
+
border: none;
|
10 |
+
padding: 10px 24px;
|
11 |
+
text-align: center;
|
12 |
+
text-decoration: none;
|
13 |
+
display: inline-block;
|
14 |
+
font-size: 16px;
|
15 |
+
margin: 4px 2px;
|
16 |
+
transition-duration: 0.4s;
|
17 |
+
cursor: pointer;
|
18 |
+
}
|
19 |
+
|
20 |
+
.stButton>button:hover {
|
21 |
+
background-color: white;
|
22 |
+
color: black;
|
23 |
+
border: 2px solid #4CAF50;
|
24 |
+
}
|