harp-dev commited on
Commit
b4a11b5
·
verified ·
1 Parent(s): 5f7378f

Refuse a recording over 10 minutes before reserving the GPU, and size each reservation

Browse files

The reservation is computed from the length (300 s of piano measured at about 15 s), and unreadable inputs are refused before the GPU is reserved.

Files changed (1) hide show
  1. app.py +26 -2
app.py CHANGED
@@ -8,6 +8,8 @@ import librosa
8
  import tempfile
9
  import os
10
 
 
 
11
  # setuptools dropped this module in version 81, and it is only needed here
12
  # to locate data files inside the installed transkun package, which
13
  # importlib.resources does from the standard library.
@@ -41,7 +43,7 @@ def load_model(device: str):
41
  checkpoint = torch.load(defaultWeight, map_location=device)
42
  model = TransKun(conf=conf).to(device)
43
 
44
- # Mirrors your checkpoint loading logic :contentReference[oaicite:3]{index=3}
45
  if "best_state_dict" in checkpoint:
46
  model.load_state_dict(checkpoint["best_state_dict"], strict=False)
47
  else:
@@ -50,7 +52,16 @@ def load_model(device: str):
50
  model.eval()
51
  return model
52
 
53
- @spaces.GPU
 
 
 
 
 
 
 
 
 
54
  def transcribe(input_file):
55
  device = "cuda" if torch.cuda.is_available() else "cpu"
56
  model = load_model(device)
@@ -84,6 +95,19 @@ def transcribe(input_file):
84
  return out_path
85
 
86
  def process_fn(input_audio_path: str) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  midi_path = transcribe(input_audio_path)
88
  return midi_path
89
 
 
8
  import tempfile
9
  import os
10
 
11
+ import soundfile as sf
12
+
13
  # setuptools dropped this module in version 81, and it is only needed here
14
  # to locate data files inside the installed transkun package, which
15
  # importlib.resources does from the standard library.
 
43
  checkpoint = torch.load(defaultWeight, map_location=device)
44
  model = TransKun(conf=conf).to(device)
45
 
46
+ # Checkpoints keep their weights under either key
47
  if "best_state_dict" in checkpoint:
48
  model.load_state_dict(checkpoint["best_state_dict"], strict=False)
49
  else:
 
52
  model.eval()
53
  return model
54
 
55
+ # The whole recording is transcribed in one pass, so the cost grows with its length
56
+ MAX_INPUT_SECONDS = 600
57
+
58
+
59
+ def gpu_seconds(input_file):
60
+ # Measured at about 15 s for 300 s of piano, building the model included, padded
61
+ return 10 + 0.1 * sf.info(input_file).duration
62
+
63
+
64
+ @spaces.GPU(duration=gpu_seconds)
65
  def transcribe(input_file):
66
  device = "cuda" if torch.cuda.is_available() else "cpu"
67
  model = load_model(device)
 
95
  return out_path
96
 
97
  def process_fn(input_audio_path: str) -> str:
98
+ # Checked before the GPU is reserved, so a request the model cannot take spends none of the
99
+ # caller's ZeroGPU allowance
100
+ if not input_audio_path:
101
+ raise gr.Error("Provide the piano recording to transcribe.")
102
+ try:
103
+ duration = sf.info(input_audio_path).duration
104
+ except Exception as exc:
105
+ raise gr.Error(f"Could not read the audio file: {exc}") from exc
106
+ if duration > MAX_INPUT_SECONDS:
107
+ raise gr.Error(
108
+ f"The recording is {duration:.1f} s long. Trim it to {MAX_INPUT_SECONDS // 60} "
109
+ "minutes or less."
110
+ )
111
  midi_path = transcribe(input_audio_path)
112
  return midi_path
113