Spaces:
Sleeping
Sleeping
File size: 3,398 Bytes
f330184 15b272c f330184 15b272c f506945 fa73991 ce70fdf f330184 f506945 f330184 f506945 f330184 f506945 fa73991 f506945 f330184 f506945 f330184 fa73991 f330184 | 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 | import sys
sys.stdout.reconfigure(line_buffering=True)
try:
import spaces
except ImportError:
# keep @spaces.GPU usable as a no-op; ZeroGPU requires this exact name.
class spaces:
class GPU:
def __init__(self, func=None, duration=60):
self.func = func
def __call__(self, *args, **kwargs):
if self.func is not None:
return self.func(*args, **kwargs)
func = args[0]
return func
from pyharp import ModelCard, build_endpoint
from pyharp.labels import LabelList, AudioLabel
import gradio as gr
import torch
from beat_this.inference import File2Beats
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
# built on CPU at import time so a broken checkpoint fails fast in the logs;
# moved to DEVICE lazily on first request, since ZeroGPU only allows CUDA
# calls made inside an @spaces.GPU-decorated call.
model = File2Beats(checkpoint_path="final0.ckpt", device="cpu", dbn=False)
model_ready = DEVICE == "cpu"
model_card = ModelCard(
name="Beat This!",
description="Detects the beat and downbeat (start-of-bar) positions in a piece of music.",
author="Francesco Foscarin, Jan Schlüter",
tags=["beat tracking", "rhythm"],
)
BEAT_COLOR = AudioLabel.rgb_color_to_int(120, 170, 255) # blue
DOWNBEAT_COLOR = AudioLabel.rgb_color_to_int(255, 130, 40) # orange
# downbeats stay in the overhead row (no amplitude); beats get an amplitude
# near the top of the waveform, so they show up as a row just below downbeats
BEAT_AMPLITUDE = 0.9
@spaces.GPU
@torch.inference_mode()
def process_fn(input_audio_path: str) -> tuple[str, LabelList]:
"""Finds beat and downbeat times in the input audio and returns them as labeled markers on the audio."""
global model, model_ready
if not model_ready:
model = File2Beats(checkpoint_path="final0.ckpt", device=DEVICE, dbn=False)
model_ready = True
beats, downbeats = model(input_audio_path)
# downbeats are a subset of beats with matching float values
downbeat_times = set(downbeats.tolist())
output_labels = LabelList()
for t in beats:
is_downbeat = float(t) in downbeat_times
if is_downbeat:
output_labels.append(
AudioLabel(t=float(t), label="downbeat", color=DOWNBEAT_COLOR)
)
else:
output_labels.append(
AudioLabel(
t=float(t), label="beat", color=BEAT_COLOR, amplitude=BEAT_AMPLITUDE
)
)
# HARP only attaches labels to an output track, so pass the audio through unchanged
return input_audio_path, output_labels
with gr.Blocks() as demo:
input_components = [
gr.Audio(type="filepath", label="Input Audio").harp_required(True),
]
output_components = [
gr.Audio(type="filepath", label="Output Audio").set_info(
"Input audio, unchanged, with detected beats and downbeats marked."
),
gr.JSON(label="Beats").set_info(
"Detected beat and downbeat times, labeled \"beat\" or \"downbeat\"."
),
]
build_endpoint(
model_card=model_card,
input_components=input_components,
output_components=output_components,
process_fn=process_fn,
)
if __name__ == "__main__":
demo.queue().launch(pwa=True)
|