ambujm22 commited on
Commit
08f8861
·
verified ·
1 Parent(s): ac1c48d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -188
app.py CHANGED
@@ -1,199 +1,26 @@
1
- # --- ABSOLUTE TOP (see above block) ---
2
- import importlib
3
- try:
4
- import spaces
5
- except Exception as e:
6
- raise RuntimeError("Failed to import 'spaces' package. Add `spaces` to requirements.txt.") from e
7
 
8
  @spaces.GPU(duration=10)
9
- def _zerogpu_probe():
10
  return "ok"
11
- # --------------------------------------
12
-
13
- # You can set env vars after the probe—safe.
14
- import os
15
- os.environ.setdefault("GRADIO_USE_CDN", "true")
16
-
17
- # Standard imports
18
- import sys
19
- import subprocess
20
- from pathlib import Path
21
- from typing import Tuple, Optional
22
 
 
23
  import gradio as gr
24
- import numpy as np
25
- import soundfile as sf
26
- from huggingface_hub import hf_hub_download
27
-
28
- USE_ZEROGPU = os.getenv("SPACE_RUNTIME", "").lower() == "zerogpu"
29
-
30
- SPACE_ROOT = Path(__file__).parent.resolve()
31
- REPO_DIR = SPACE_ROOT / "SonicMasterRepo"
32
- WEIGHTS_REPO = "amaai-lab/SonicMaster"
33
- WEIGHTS_FILE = "model.safetensors"
34
- CACHE_DIR = SPACE_ROOT / "weights"
35
- CACHE_DIR.mkdir(parents=True, exist_ok=True)
36
-
37
- def get_weights_path() -> Path:
38
- return Path(
39
- hf_hub_download(
40
- repo_id=WEIGHTS_REPO,
41
- filename=WEIGHTS_FILE,
42
- local_dir=CACHE_DIR.as_posix(),
43
- local_dir_use_symlinks=False,
44
- force_download=False,
45
- resume_download=True,
46
- )
47
- )
48
-
49
- def ensure_repo() -> Path:
50
- if not REPO_DIR.exists():
51
- subprocess.run(
52
- ["git", "clone", "--depth", "1",
53
- "https://github.com/AMAAI-Lab/SonicMaster",
54
- REPO_DIR.as_posix()],
55
- check=True,
56
- )
57
- if REPO_DIR.as_posix() not in sys.path:
58
- sys.path.append(REPO_DIR.as_posix())
59
- return REPO_DIR
60
-
61
- def build_examples():
62
- repo = ensure_repo()
63
- wav_dir = repo / "samples" / "inputs"
64
- wav_paths = sorted(p for p in wav_dir.glob("*.wav") if p.is_file())
65
- prompts = [
66
- "Increase the clarity of this song by emphasizing treble frequencies.",
67
- "Make this song sound more boomy by amplifying the low end bass frequencies.",
68
- "Can you make this sound louder, please?",
69
- "Make the audio smoother and less distorted.",
70
- "Improve the balance in this song.",
71
- "Disentangle the left and right channels to give this song a stereo feeling.",
72
- "Correct the unnatural frequency emphasis. Reduce the roominess or echo.",
73
- "Raise the level of the vocals, please.",
74
- "Increase the clarity of this song by emphasizing treble frequencies.",
75
- "Please, dereverb this audio.",
76
- ]
77
- return [[p.as_posix(), prompts[i] if i < len(prompts) else prompts[-1]]
78
- for i, p in enumerate(wav_paths[:10])]
79
-
80
- def save_temp_wav(wav: np.ndarray, sr: int, path: Path):
81
- if wav.ndim == 2 and wav.shape[0] < wav.shape[1]:
82
- wav = wav.T
83
- sf.write(path.as_posix(), wav, sr)
84
-
85
- def read_audio(path: str) -> Tuple[np.ndarray, int]:
86
- wav, sr = sf.read(path, always_2d=False)
87
- return wav.astype(np.float32) if wav.dtype == np.float64 else wav, sr
88
-
89
- def run_sonicmaster_cli(input_wav_path: Path,
90
- prompt: str,
91
- out_path: Path,
92
- _logs: list,
93
- progress: Optional[gr.Progress] = None) -> bool:
94
- if progress: progress(0.15, desc="Loading weights & repo")
95
- ckpt = get_weights_path()
96
- repo = ensure_repo()
97
 
98
- py = sys.executable or "python3"
99
- script_candidates = [repo / "infer_single.py"]
100
 
101
- CANDIDATE_CMDS = []
102
- for script in script_candidates:
103
- if script.exists():
104
- CANDIDATE_CMDS.append([
105
- py, script.as_posix(),
106
- "--ckpt", ckpt.as_posix(),
107
- "--input", input_wav_path.as_posix(),
108
- "--prompt", prompt,
109
- "--output", out_path.as_posix(),
110
- ])
111
- CANDIDATE_CMDS.append([
112
- py, script.as_posix(),
113
- "--weights", ckpt.as_posix(),
114
- "--input", input_wav_path.as_posix(),
115
- "--text", prompt,
116
- "--out", out_path.as_posix(),
117
- ])
118
-
119
- for idx, cmd in enumerate(CANDIDATE_CMDS, start=1):
120
- try:
121
- if progress: progress(0.35 + 0.05*idx, desc=f"Running inference (try {idx})")
122
- subprocess.run(cmd, capture_output=True, text=True, check=True, env=os.environ.copy())
123
- if out_path.exists() and out_path.stat().st_size > 0:
124
- if progress: progress(0.9, desc="Post-processing output")
125
- return True
126
- except Exception:
127
- continue
128
- return False
129
-
130
- @spaces.GPU(duration=180)
131
- def enhance_on_gpu(input_path: str, prompt: str, output_path: str) -> bool:
132
- try:
133
- import torch # ensure CUDA init happens in GPU context
134
- except Exception:
135
- pass
136
- from pathlib import Path as _P
137
- return run_sonicmaster_cli(_P(input_path), prompt, _P(output_path), _logs=[], progress=None)
138
-
139
- def enhance_audio_ui(audio_path: str,
140
- prompt: str,
141
- progress=gr.Progress(track_tqdm=True)) -> Tuple[int, np.ndarray]:
142
- if not audio_path or not prompt:
143
- raise gr.Error("Please provide audio and a text prompt.")
144
-
145
- wav, sr = read_audio(audio_path)
146
- tmp_in, tmp_out = SPACE_ROOT / "tmp_in.wav", SPACE_ROOT / "tmp_out.wav"
147
- if tmp_out.exists():
148
- try: tmp_out.unlink()
149
- except: pass
150
- save_temp_wav(wav, sr, tmp_in)
151
-
152
- if progress: progress(0.3, desc="Starting inference")
153
- if USE_ZEROGPU:
154
- ok = enhance_on_gpu(tmp_in.as_posix(), prompt, tmp_out.as_posix())
155
- else:
156
- ok = run_sonicmaster_cli(tmp_in, prompt, tmp_out, _logs=[], progress=progress)
157
-
158
- if ok and tmp_out.exists() and tmp_out.stat().st_size > 0:
159
- out_wav, out_sr = read_audio(tmp_out.as_posix())
160
- return (out_sr, out_wav)
161
- else:
162
- # If inference fails, return original audio (your chosen fallback).
163
- return (sr, wav)
164
-
165
- with gr.Blocks(title="SonicMaster – Text-Guided Restoration & Mastering", fill_height=True) as demo:
166
- gr.Markdown("## 🎧 SonicMaster\nUpload or choose an example, write a text prompt, then click **Enhance**.")
167
- with gr.Row():
168
- with gr.Column():
169
- in_audio = gr.Audio(label="Input Audio", type="filepath")
170
- prompt = gr.Textbox(label="Text Prompt", placeholder="e.g., reduce reverb")
171
- run_btn = gr.Button("🚀 Enhance", variant="primary")
172
- gr.Examples(examples=build_examples(), inputs=[in_audio, prompt])
173
- with gr.Column():
174
- out_audio = gr.Audio(label="Enhanced Audio (output)")
175
- run_btn.click(fn=enhance_audio_ui,
176
- inputs=[in_audio, prompt],
177
- outputs=[out_audio],
178
- concurrency_limit=1)
179
-
180
- from fastapi import FastAPI, Request
181
- from starlette.responses import PlainTextResponse
182
- from starlette.requests import ClientDisconnect
183
-
184
- # Preload light assets after probe so import won’t fail before detector.
185
- _ = get_weights_path()
186
- _ = ensure_repo()
187
 
 
188
  app = FastAPI()
189
 
190
- @app.exception_handler(ClientDisconnect)
191
- async def client_disconnect_handler(request: Request, exc: ClientDisconnect):
192
- return PlainTextResponse("Client disconnected", status_code=499)
193
-
194
- # (Queue() at mount time is fine)
195
- app = gr.mount_gradio_app(app, demo.queue(max_size=16), path="/")
196
 
197
- # if __name__ == "__main__":
198
- # import uvicorn
199
- # uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ # --- ZeroGPU must see a GPU-decorated function at import time ---
2
+ import spaces
 
 
 
 
3
 
4
  @spaces.GPU(duration=10)
5
+ def _gpu_probe():
6
  return "ok"
 
 
 
 
 
 
 
 
 
 
 
7
 
8
+ # --- Gradio app kept trivial to prove boot path ---
9
  import gradio as gr
10
+ from fastapi import FastAPI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ def echo(x):
13
+ return f"ok: {x}"
14
 
15
+ with gr.Blocks(title="Hello") as demo:
16
+ inp = gr.Textbox(label="Say something")
17
+ out = gr.Textbox(label="Reply")
18
+ inp.submit(echo, inp, out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ # Expose *either* 'demo' or a FastAPI 'app'. We'll use FastAPI + mount:
21
  app = FastAPI()
22
 
23
+ # Mount Gradio at root so Spaces healthcheck to "/" gets 200
24
+ app = gr.mount_gradio_app(app, demo.queue(), path="/")
 
 
 
 
25
 
26
+ # DO NOT run uvicorn here — Spaces runs the server.