JohnyBonony commited on
Commit
25ddb7c
·
verified ·
1 Parent(s): 933c367

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +27 -10
  2. app.py +95 -47
  3. requirements.txt +10 -8
README.md CHANGED
@@ -1,16 +1,33 @@
1
  ---
2
- title: image
3
- emoji: 📈
4
- colorFrom: pink
5
- colorTo: yellow
6
  sdk: gradio
7
- sdk_version: 6.20.0
8
- python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
11
- hf_oauth: true
12
- hf_oauth_scopes:
13
- - inference-api
14
  ---
15
 
16
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: ZeroGPU Strip Bench
3
+ emoji: ⏱️
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ python_version: "3.10"
 
8
  app_file: app.py
9
  pinned: false
 
 
 
10
  ---
11
 
12
+ # ZeroGPU strip-pass benchmark (throwaway test app)
13
+
14
+ Standalone benchmark to measure real timing of the vocal-isolation pass — the
15
+ same model the live Voice Remover's Step 1 uses
16
+ (`mel_band_roformer_vocals_becruily`) — on this Space's ZeroGPU hardware.
17
+
18
+ Not connected to the production site, its password gate, or its backend.
19
+ Purpose is purely to get real load-time / inference-time numbers before
20
+ deciding whether ZeroGPU is worth building into the actual product.
21
+
22
+ ## Use
23
+
24
+ Upload a song, click "Run strip pass". Reports model-load time, separation
25
+ time, total, the GPU name, and an estimate of how many runs the 2-min/day free
26
+ IP-based quota buys per visitor (excludes any per-region splits on top).
27
+
28
+ ## Deploy
29
+
30
+ Space hardware must be set to ZeroGPU and SDK to Gradio (already required for
31
+ `spaces.GPU` to work at all — Docker/Static Spaces can't schedule onto
32
+ ZeroGPU). Upload `app.py`, `requirements.txt`, and this `README.md` to the
33
+ Space's file root.
app.py CHANGED
@@ -1,52 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
- import gradio as gr
 
 
 
3
  import spaces
 
4
  import torch
5
- from diffusers import DiffusionPipeline
6
-
7
- device = "cuda" if torch.cuda.is_available() else "cpu"
8
-
9
- # Automatically grab the token you saved in the Space settings
10
- hf_token = os.getenv("HF_TOKEN")
11
-
12
- # Pass the token explicitly into the from_pretrained function
13
- pipe = DiffusionPipeline.from_pretrained(
14
- "black-forest-labs/FLUX.1-schnell",
15
- torch_dtype=torch.bfloat16,
16
- token=hf_token
17
- )
18
- pipe.to(device)
19
-
20
- @spaces.GPU
21
- def generate_image(prompt):
22
- image = pipe(
23
- prompt,
24
- num_inference_steps=4,
25
- guidance_scale=0.0,
26
- max_sequence_length=256
27
- ).images[0]
28
- return image
29
-
30
- # (Rest of your Gradio interface layout remains exactly the same!)
31
- with gr.Blocks() as demo:
32
- gr.Markdown("# ZeroGPU Fast Image Generator")
33
- gr.Markdown("Using `FLUX.1-schnell` for ultra-fast, high-quality rendering.")
34
-
35
- with gr.Row():
36
- with gr.Column():
37
- prompt_input = gr.Textbox(
38
- label="Enter your prompt",
39
- placeholder="A futuristic cybernetic cat sitting on a neon rooftop...",
40
- lines=3
41
- )
42
- generate_btn = gr.Button("Generate", variant="primary")
43
- with gr.Column():
44
- image_output = gr.Image(label="Resulting Image")
45
-
46
- generate_btn.click(
47
- fn=generate_image,
48
- inputs=prompt_input,
49
- outputs=image_output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  )
 
 
 
 
51
 
52
- demo.launch()
 
1
+ """ZeroGPU strip-pass benchmark — throwaway test app.
2
+
3
+ Standalone Gradio app, NOT part of the production site. Runs the exact same
4
+ vocal-isolation model the live Voice Remover's Step 1 uses
5
+ (mel_band_roformer_vocals_becruily) and times it on this Space's ZeroGPU
6
+ hardware, so we can decide with real numbers whether ZeroGPU is viable as a
7
+ backend before touching anything production-facing.
8
+
9
+ Deploy: create/point a ZeroGPU-hardware Space at this folder (sdk: gradio,
10
+ see README.md). Upload a song, click "Run strip pass".
11
+ """
12
  import os
13
+ import time
14
+ import traceback
15
+ from pathlib import Path
16
+
17
  import spaces
18
+ import gradio as gr
19
  import torch
20
+ import torchaudio
21
+ from audio_separator.separator import Separator
22
+
23
+ MODELS_DIR = Path(os.environ.get("MODELS_DIR", "/tmp/models"))
24
+ MODELS_DIR.mkdir(parents=True, exist_ok=True)
25
+
26
+ # Same model the live site's Step 1 ("Isolate vocals — becruily") uses.
27
+ VOCAL_MODEL = "mel_band_roformer_vocals_becruily.ckpt"
28
+
29
+ # Fetch the checkpoint once at Space startup — CPU-only, no GPU needed — so the
30
+ # timed run below measures disk->GPU load, not an internet download.
31
+ print(f"[startup] fetching {VOCAL_MODEL} ...", flush=True)
32
+ _warm = Separator(output_dir="/tmp", model_file_dir=str(MODELS_DIR))
33
+ _warm.load_model(model_filename=VOCAL_MODEL)
34
+ del _warm
35
+ print("[startup] model cached on disk.", flush=True)
36
+
37
+
38
+ def _normalize(src: str) -> str:
39
+ """Approximates production's _normalize_for_sep (stereo / 32-bit float /
40
+ min 30s) so the timed input shape matches what RoFormer sees live."""
41
+ wf, sr = torchaudio.load(src)
42
+ if wf.shape[0] == 1:
43
+ wf = wf.repeat(2, 1)
44
+ elif wf.shape[0] > 2:
45
+ wf = wf[:2]
46
+ min_samples = sr * 30
47
+ if wf.shape[1] < min_samples:
48
+ pad = torch.zeros(wf.shape[0], min_samples - wf.shape[1], dtype=wf.dtype)
49
+ wf = torch.cat([wf, pad], dim=1)
50
+ out = "/tmp/_bench_input.wav"
51
+ torchaudio.save(out, wf, sr, encoding="PCM_F", bits_per_sample=32)
52
+ return out
53
+
54
+
55
+ @spaces.GPU(duration=110)
56
+ def run_benchmark(song_path):
57
+ if song_path is None:
58
+ return "Upload a song first."
59
+
60
+ try:
61
+ gpu_name = torch.cuda.get_device_name(0) if torch.cuda.is_available() else "no GPU visible"
62
+
63
+ t0 = time.perf_counter()
64
+ sep = Separator(output_dir="/tmp", output_format="WAV", model_file_dir=str(MODELS_DIR))
65
+ sep.load_model(model_filename=VOCAL_MODEL)
66
+ t1 = time.perf_counter()
67
+
68
+ sep_input = _normalize(song_path)
69
+ out_names = sep.separate(sep_input)
70
+ t2 = time.perf_counter()
71
+
72
+ load_s, sep_s, total_s = t1 - t0, t2 - t1, t2 - t0
73
+ runs_per_day = max(1, int(120 // total_s)) if total_s > 0 else "?"
74
+
75
+ return (
76
+ f"GPU: {gpu_name}\n\n"
77
+ f"Model load + move-to-device: {load_s:.1f}s\n"
78
+ f"Separation (inference): {sep_s:.1f}s\n"
79
+ f"Total: {total_s:.1f}s\n\n"
80
+ f"Output stems: {out_names}\n\n"
81
+ f"2 min/day free quota ÷ this total ≈ {runs_per_day} run(s)/day per visitor "
82
+ f"(before counting any region splits on top of this strip pass)."
83
+ )
84
+ except Exception:
85
+ return "Error:\n" + traceback.format_exc()
86
+
87
+
88
+ with gr.Blocks(title="ZeroGPU strip-pass benchmark") as demo:
89
+ gr.Markdown(
90
+ "### ZeroGPU strip-pass benchmark\n"
91
+ "Throwaway test app — not the production site. Upload a song and run "
92
+ "the same vocal-isolation model the live site's Step 1 uses, timed on "
93
+ "this Space's GPU, to get real numbers on whether ZeroGPU is viable."
94
  )
95
+ audio_in = gr.Audio(label="Song", type="filepath")
96
+ run_btn = gr.Button("Run strip pass", variant="primary")
97
+ result = gr.Textbox(label="Timing", lines=9)
98
+ run_btn.click(fn=run_benchmark, inputs=audio_in, outputs=result)
99
 
100
+ demo.launch()
requirements.txt CHANGED
@@ -1,8 +1,10 @@
1
- gradio
2
- spaces
3
- torch
4
- transformers
5
- diffusers
6
- accelerate
7
- sentencepiece
8
- protobuf
 
 
 
1
+ torch==2.5.1
2
+ torchaudio==2.5.1
3
+ numpy>=2.0,<2.1
4
+ numba>=0.60
5
+ audio-separator==0.44.2
6
+ pyyaml==6.0.3
7
+ soundfile==0.13.1
8
+ librosa==0.11.0
9
+ scipy==1.15.3
10
+ certifi