Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,20 +1,6 @@
|
|
| 1 |
# ============================================================================
|
| 2 |
# app.py — ZeroGPU deployment via gradio.Server
|
| 3 |
#
|
| 4 |
-
# gradio.Server extends FastAPI, so:
|
| 5 |
-
# - @app.get("/") serves the custom HTML editor (unchanged)
|
| 6 |
-
# - @app.api() wraps the GPU transcription with Gradio's queue
|
| 7 |
-
# + ZeroGPU allocation (@spaces.GPU)
|
| 8 |
-
# - @app.post("/analyze") and @app.post("/pmi") are plain FastAPI routes
|
| 9 |
-
# (CPU only — key estimation / PMI, no GPU)
|
| 10 |
-
#
|
| 11 |
-
# IMPORTANT (ZeroGPU): the browser must call the @app.api() transcription
|
| 12 |
-
# endpoint through @gradio/client (see transcription-editor.html), NOT a bare
|
| 13 |
-
# fetch(), so the HF iframe auth headers reach ZeroGPU for quota handling.
|
| 14 |
-
#
|
| 15 |
-
# This is a first-draft port. The ZeroGPU runtime differs from the Docker
|
| 16 |
-
# image (torch build, CUDA, FFmpeg), so the torchcodec / demucs monkeypatches
|
| 17 |
-
# in pipeline.py may need re-checking on the live Space.
|
| 18 |
# ============================================================================
|
| 19 |
import os, base64, tempfile, time
|
| 20 |
|
|
@@ -113,33 +99,7 @@ def _audio_seconds(path):
|
|
| 113 |
return 30.0 # unknown -> assume a modest clip
|
| 114 |
|
| 115 |
def _gpu_duration(audio_path, instrument="vocals"):
|
| 116 |
-
|
| 117 |
-
# cold, 35.1 s clip: demucs 1.20 s + inference 1.98 s + post 0.01 s = 3.2 s
|
| 118 |
-
# warm, 40.9 s clip: demucs 0.50 s + inference 1.89 s + post 0.01 s = 2.4 s
|
| 119 |
-
# Two things follow. Inference barely moves with clip length in this range
|
| 120 |
-
# (1.98 s for 35 s of audio vs 1.89 s for 41 s), so scaling the estimate
|
| 121 |
-
# linearly with duration is mostly wrong -- fixed cost dominates. And a cold
|
| 122 |
-
# worker's demucs runs 2.8x slower than a warm one (29 vs 82 s of audio per
|
| 123 |
-
# second) as CUDA kernels and weights warm up. Across five clips (160 s of
|
| 124 |
-
# audio) the total was ~48 s of GPU time, i.e. ~6-7 s per call of pure
|
| 125 |
-
# overhead against 2-3 s of actual compute.
|
| 126 |
-
#
|
| 127 |
-
# Two formulas, because a cold worker and a warm one are not comparable: the
|
| 128 |
-
# cold path pays kernel warm-up and disk->VRAM weight streaming on top of
|
| 129 |
-
# the same compute.
|
| 130 |
-
#
|
| 131 |
-
# This buys queue position, NOT quota. Quota is charged on actual seconds
|
| 132 |
-
# used and the declaration only gates admission ("do you have this many
|
| 133 |
-
# seconds left?"), so at ~9 s of real cost per call the gate barely bites
|
| 134 |
-
# until the quota is nearly spent -- declaring 15 s instead of 22 s is worth
|
| 135 |
-
# about one extra call in thirty. What it does buy is priority: among queued
|
| 136 |
-
# requests, a shorter declared duration ranks higher.
|
| 137 |
-
#
|
| 138 |
-
# The warm claim is time-limited on purpose. ZeroGPU recycles idle workers,
|
| 139 |
-
# so "we succeeded once" does not mean the NEXT request lands on a warm one.
|
| 140 |
-
# Past WARM_WINDOW we assume cold again -- under-declaring is the worse
|
| 141 |
-
# error, because the declaration is also the hard timeout: the task is killed
|
| 142 |
-
# mid-run and the quota is spent anyway.
|
| 143 |
sec = _audio_seconds(_resolve(audio_path))
|
| 144 |
if (time.monotonic() - _last_gpu_ok) < WARM_WINDOW:
|
| 145 |
return int(max(15, min(120, 8 + 0.2 * sec))) # ~1.7x over measured
|
|
@@ -324,10 +284,7 @@ async def pmi_api(midi_a: UploadFile = File(...), midi_b: UploadFile = File(...)
|
|
| 324 |
except OSError: pass
|
| 325 |
|
| 326 |
|
|
|
|
|
|
|
| 327 |
if __name__ == "__main__":
|
| 328 |
-
# ssr_mode=False: Spaces force SSR on via an env var, which makes Gradio put a
|
| 329 |
-
# Node process on 7860 that proxies to Python on 7861. When that layer fails to
|
| 330 |
-
# answer, the platform's readiness probe never passes and the Space sits on
|
| 331 |
-
# "Starting" forever even though the log shows the app running. We serve our own
|
| 332 |
-
# HTML anyway, so server-side rendering buys us nothing here.
|
| 333 |
app.launch(ssr_mode=False)
|
|
|
|
| 1 |
# ============================================================================
|
| 2 |
# app.py — ZeroGPU deployment via gradio.Server
|
| 3 |
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
# ============================================================================
|
| 5 |
import os, base64, tempfile, time
|
| 6 |
|
|
|
|
| 99 |
return 30.0 # unknown -> assume a modest clip
|
| 100 |
|
| 101 |
def _gpu_duration(audio_path, instrument="vocals"):
|
| 102 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
sec = _audio_seconds(_resolve(audio_path))
|
| 104 |
if (time.monotonic() - _last_gpu_ok) < WARM_WINDOW:
|
| 105 |
return int(max(15, min(120, 8 + 0.2 * sec))) # ~1.7x over measured
|
|
|
|
| 284 |
except OSError: pass
|
| 285 |
|
| 286 |
|
| 287 |
+
demo = app
|
| 288 |
+
|
| 289 |
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
app.launch(ssr_mode=False)
|