harp-dev commited on
Commit
cd3b1e6
·
verified ·
1 Parent(s): 3c17a69

Check inputs before reserving the GPU, and skip it entirely for a silent input.

Browse files
Files changed (1) hide show
  1. app.py +31 -18
app.py CHANGED
@@ -32,35 +32,48 @@ model_card = ModelCard(
32
  )
33
 
34
 
35
- @spaces.GPU
36
- @torch.inference_mode()
37
  def process_fn(input_audio_path: str, output_sample_rate: str) -> str:
 
 
38
  if not input_audio_path:
39
  raise gr.Error("Choose an audio file.")
40
  audio, input_rate = torchaudio.load(input_audio_path)
41
- audio = audio.mean(dim=0, keepdim=True)
42
  if audio.shape[-1] == 0:
43
  raise gr.Error("The audio file is empty.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  output_rate = int(output_sample_rate)
45
  output_length = ceil(audio.shape[-1] * output_rate / input_rate)
46
  native_length = ceil(audio.shape[-1] * SAMPLE_RATE / input_rate)
47
 
48
- # Upstream divides by the input peak, so silence bypasses inference.
49
- if audio.count_nonzero() == 0:
50
- result = torch.zeros(1, output_length)
51
- else:
52
- minimum_length = ceil(2048 * input_rate / SAMPLE_RATE)
53
- if audio.shape[-1] < minimum_length:
54
- audio = F.pad(audio, (0, minimum_length - audio.shape[-1]))
55
- result = model.generate(audio, input_rate, SAMPLE_RATE, timestep=1).cpu()
56
- result = result[..., :native_length]
57
- if output_rate != SAMPLE_RATE:
58
- result = torchaudio.functional.resample(result, SAMPLE_RATE, output_rate)
59
- result = result[..., :output_length]
60
- peak = result.abs().max()
61
- if peak > 1:
62
- result *= 0.99 / peak
63
 
 
64
  # mkdtemp, not a context manager: that would delete the directory on exit,
65
  # taking the written file with it before the caller can read it, which is
66
  # what the block-cache call here was working around. That also reached for
 
32
  )
33
 
34
 
 
 
35
  def process_fn(input_audio_path: str, output_sample_rate: str) -> str:
36
+ # Checked before the GPU is reserved, so a request the model cannot take spends none of the
37
+ # caller's ZeroGPU allowance
38
  if not input_audio_path:
39
  raise gr.Error("Choose an audio file.")
40
  audio, input_rate = torchaudio.load(input_audio_path)
 
41
  if audio.shape[-1] == 0:
42
  raise gr.Error("The audio file is empty.")
43
+
44
+ # Upstream divides by the input peak, so silence bypasses inference, and the GPU with it
45
+ if audio.count_nonzero() == 0:
46
+ output_rate = int(output_sample_rate)
47
+ return save(torch.zeros(1, ceil(audio.shape[-1] * output_rate / input_rate)), output_rate)
48
+
49
+ return extend(input_audio_path, output_sample_rate)
50
+
51
+
52
+ @spaces.GPU
53
+ @torch.inference_mode()
54
+ def extend(input_audio_path: str, output_sample_rate: str) -> str:
55
+ audio, input_rate = torchaudio.load(input_audio_path)
56
+ audio = audio.mean(dim=0, keepdim=True)
57
  output_rate = int(output_sample_rate)
58
  output_length = ceil(audio.shape[-1] * output_rate / input_rate)
59
  native_length = ceil(audio.shape[-1] * SAMPLE_RATE / input_rate)
60
 
61
+ minimum_length = ceil(2048 * input_rate / SAMPLE_RATE)
62
+ if audio.shape[-1] < minimum_length:
63
+ audio = F.pad(audio, (0, minimum_length - audio.shape[-1]))
64
+ result = model.generate(audio, input_rate, SAMPLE_RATE, timestep=1).cpu()
65
+ result = result[..., :native_length]
66
+ if output_rate != SAMPLE_RATE:
67
+ result = torchaudio.functional.resample(result, SAMPLE_RATE, output_rate)
68
+ result = result[..., :output_length]
69
+ peak = result.abs().max()
70
+ if peak > 1:
71
+ result *= 0.99 / peak
72
+
73
+ return save(result, output_rate)
74
+
 
75
 
76
+ def save(result: torch.Tensor, output_rate: int) -> str:
77
  # mkdtemp, not a context manager: that would delete the directory on exit,
78
  # taking the written file with it before the caller can read it, which is
79
  # what the block-cache call here was working around. That also reached for