tddandroid commited on
Commit
8fa9a24
·
verified ·
1 Parent(s): c4c11ab

Move GPU decorator to transcription; provider chain runs on CPU; report chain errors

Browse files
Files changed (1) hide show
  1. app.py +28 -8
app.py CHANGED
@@ -61,14 +61,25 @@ def _audio_duration(path):
61
  return 0.0
62
 
63
 
 
 
 
 
 
 
 
 
 
64
  def transcribe(audio_path, model_choice):
65
  if not audio_path:
66
  return None, "", "Upload a song first."
67
- jid = _job()
68
  try:
69
- res = do_transcribe(jid, Path(audio_path), model_choice or "small")
70
- except Exception as e:
71
- return None, "", f"⚠️ Transcription failed — {type(e).__name__}: {e}"
 
 
 
72
  segs = res["segments"]
73
  text = "\n".join(f"{_fmt_ts(s['start'])} {s['text']}" for s in segs)
74
  return segs, text, f"Transcribed {len(segs)} lines ({res['language']}, {res['duration']:.0f}s). Now build the director plan."
@@ -183,10 +194,11 @@ def render_smooth(clips, windows, audio, segments, out_path):
183
  return Path(out_path)
184
 
185
 
186
- @spaces.GPU(duration=120)
187
  def ai_clip(image_path, prompt, novai_key, deepinfra_key, novita_key, fal_key):
188
  """Generate ONE AI clip through the provider chain (first free tier that
189
- answers wins). This is the Space's @spaces.GPU handler."""
 
 
190
  keys = _keys(novai_key, deepinfra_key, novita_key, fal_key)
191
  if not any(keys.values()):
192
  raise gr.Error("No provider keys available — add one in the key fields above or save them as Space secrets.")
@@ -215,6 +227,10 @@ def make_video(audio_path, image_path, segs, shots, use_ai,
215
  return
216
  keys = _keys(novai_key, deepinfra_key, novita_key, fal_key)
217
  chain_on = bool(use_ai and any(keys.values()))
 
 
 
 
218
  duration = _audio_duration(audio_path)
219
  if segs is None:
220
  progress(0.05, desc="Transcribing your song…")
@@ -238,8 +254,10 @@ def make_video(audio_path, image_path, segs, shots, use_ai,
238
  try:
239
  path, who = providers.generate_with_chain(keys, image_path, shot["prompt"], target, out)
240
  made = (path, who)
241
- except providers.ProviderError:
242
  made = None # photo-zoom fills this shot
 
 
243
  if made is None:
244
  jid = _job()
245
  res = do_photoclip(jid, Path(image_path), target, variant=i % 4)
@@ -257,7 +275,9 @@ def make_video(audio_path, image_path, segs, shots, use_ai,
257
  res = do_render(jid, Path(audio_path), [p.name for p in clip_paths], "", segs)
258
  final = FILES / Path(res["video_url"]).name
259
  how = f"{total} shots, hard-cut render (crossfade unavailable)"
260
- yield str(final), f"Done — your music video is ready ({how}).\n" + "\n".join(used)
 
 
261
 
262
 
263
  with gr.Blocks(title="AllOutMV") as demo:
 
61
  return 0.0
62
 
63
 
64
+ @spaces.GPU(duration=120)
65
+ def _transcribe_gpu(audio_path, model_choice):
66
+ """Real GPU work (Whisper on CUDA) — the Space's @spaces.GPU function.
67
+ ZeroGPU attaches the GPU only inside decorated calls and aborts decorated
68
+ functions that never use it, so the GPU belongs on transcription, not on
69
+ the HTTP provider chain."""
70
+ return do_transcribe(_job(), Path(audio_path), model_choice or "small")
71
+
72
+
73
  def transcribe(audio_path, model_choice):
74
  if not audio_path:
75
  return None, "", "Upload a song first."
 
76
  try:
77
+ res = _transcribe_gpu(audio_path, model_choice) # fast path: real GPU
78
+ except Exception:
79
+ try:
80
+ res = do_transcribe(_job(), Path(audio_path), model_choice or "small") # CPU fallback
81
+ except Exception as e:
82
+ return None, "", f"⚠️ Transcription failed — {type(e).__name__}: {e}"
83
  segs = res["segments"]
84
  text = "\n".join(f"{_fmt_ts(s['start'])} {s['text']}" for s in segs)
85
  return segs, text, f"Transcribed {len(segs)} lines ({res['language']}, {res['duration']:.0f}s). Now build the director plan."
 
194
  return Path(out_path)
195
 
196
 
 
197
  def ai_clip(image_path, prompt, novai_key, deepinfra_key, novita_key, fal_key):
198
  """Generate ONE AI clip through the provider chain (first free tier that
199
+ answers wins). Deliberately NOT @spaces.GPU: ZeroGPU aborts decorated
200
+ functions that never touch the GPU, and this work is pure HTTP polling —
201
+ it runs on CPU. The decorator lives on _transcribe_gpu instead."""
202
  keys = _keys(novai_key, deepinfra_key, novita_key, fal_key)
203
  if not any(keys.values()):
204
  raise gr.Error("No provider keys available — add one in the key fields above or save them as Space secrets.")
 
227
  return
228
  keys = _keys(novai_key, deepinfra_key, novita_key, fal_key)
229
  chain_on = bool(use_ai and any(keys.values()))
230
+ chain_note = ""
231
+ if use_ai and not chain_on:
232
+ chain_note = "\n\n⚠️ Provider chain was OFF — no provider keys found (key fields empty and no Space secrets visible), so every shot used photo-zoom."
233
+ chain_error = None
234
  duration = _audio_duration(audio_path)
235
  if segs is None:
236
  progress(0.05, desc="Transcribing your song…")
 
254
  try:
255
  path, who = providers.generate_with_chain(keys, image_path, shot["prompt"], target, out)
256
  made = (path, who)
257
+ except providers.ProviderError as e:
258
  made = None # photo-zoom fills this shot
259
+ if chain_error is None:
260
+ chain_error = str(e)
261
  if made is None:
262
  jid = _job()
263
  res = do_photoclip(jid, Path(image_path), target, variant=i % 4)
 
275
  res = do_render(jid, Path(audio_path), [p.name for p in clip_paths], "", segs)
276
  final = FILES / Path(res["video_url"]).name
277
  how = f"{total} shots, hard-cut render (crossfade unavailable)"
278
+ if chain_error:
279
+ chain_note += f"\n\n⚠️ Provider chain report (first failure): {chain_error}"
280
+ yield str(final), f"Done — your music video is ready ({how}).\n" + "\n".join(used) + chain_note
281
 
282
 
283
  with gr.Blocks(title="AllOutMV") as demo: