Hug0endob commited on
Commit
5bf99a0
·
verified ·
1 Parent(s): 7f60ea8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -19
app.py CHANGED
@@ -1,4 +1,6 @@
1
  #!/usr/bin/env python3
 
 
2
  import os
3
  import subprocess
4
  import tempfile
@@ -42,9 +44,9 @@ def ext_from_src(src: str) -> str:
42
 
43
  def fetch_bytes(src: str, stream_threshold=STREAM_THRESHOLD, timeout=60) -> bytes:
44
  if is_remote(src):
45
- # Try HEAD first to detect size; fallback to GET
46
  try:
47
- h = requests.head(src, timeout=8, allow_redirects=True)
48
  h.raise_for_status()
49
  cl = h.headers.get("content-length")
50
  if cl and int(cl) > stream_threshold:
@@ -62,7 +64,6 @@ def fetch_bytes(src: str, stream_threshold=STREAM_THRESHOLD, timeout=60) -> byte
62
  finally:
63
  try: os.remove(path)
64
  except Exception: pass
65
- # small content or no content-length: simple GET
66
  except Exception:
67
  pass
68
  with requests.get(src, timeout=timeout) as r:
@@ -100,22 +101,21 @@ def b64_jpeg(img_bytes: bytes) -> str:
100
  def extract_best_frames_bytes(media_path: str, sample_count: int = 5, timeout_probe: int = 10, timeout_extract: int = 15) -> list:
101
  if not FFMPEG_BIN or not os.path.exists(media_path):
102
  return []
103
- probe_cmd = [FFMPEG_BIN, "-v", "error", "-show_entries", "format=duration",
104
- "-of", "default=noprint_wrappers=1:nokey=1", media_path]
105
  try:
106
- out = subprocess.check_output(probe_cmd, timeout=timeout_probe).strip()
107
- duration = float(out) if out else None
 
 
108
  except Exception:
109
- duration = None
110
- if duration and duration > 0:
111
- timestamps = [(duration * i) / (sample_count + 1) for i in range(1, sample_count + 1)]
112
- else:
113
- timestamps = [0.5, 1.0, 2.0][:sample_count]
114
  frames = []
115
  for i, t in enumerate(timestamps):
116
  fd, tmp = tempfile.mkstemp(suffix=f"_{i}.jpg")
117
  os.close(fd)
118
- cmd = [FFMPEG_BIN, "-nostdin", "-y", "-i", media_path, "-ss", str(t), "-frames:v", "1", "-q:v", "2", tmp]
119
  try:
120
  subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=timeout_extract)
121
  if os.path.exists(tmp) and os.path.getsize(tmp) > 0:
@@ -156,14 +156,15 @@ def build_messages_for_text(prompt: str, extra: str) -> list:
156
 
157
  def extract_text_from_response(res, parts: list):
158
  try:
159
- choices = getattr(res, "choices", None) or res.get("choices", [])
160
  except Exception:
161
  choices = []
162
  if not choices:
163
  parts.append(str(res))
164
  return
165
  try:
166
- msg = choices[0].message
 
167
  if isinstance(msg, dict):
168
  content = msg.get("content")
169
  else:
@@ -210,7 +211,8 @@ def process_media(src: str, custom_prompt: str, api_key: str) -> str:
210
  is_video = ext in VIDEO_EXTS
211
  if is_remote(src):
212
  try:
213
- h = requests.head(src, timeout=8, allow_redirects=True)
 
214
  ctype = (h.headers.get("content-type") or "").lower()
215
  if ctype.startswith("video/"):
216
  is_video = True; is_image = False
@@ -259,6 +261,7 @@ css = ".preview_media img, .preview_media video { max-width: 100%; height: auto;
259
  def load_preview(url: str):
260
  if not url:
261
  return None, None, ""
 
262
  if not is_remote(url) and os.path.exists(url):
263
  ext = ext_from_src(url)
264
  if ext in VIDEO_EXTS:
@@ -271,15 +274,17 @@ def load_preview(url: str):
271
  return img.convert("RGB"), None, "Image"
272
  except Exception:
273
  return None, None, "Preview failed"
274
- # Remote: prefer HEAD, then GET fallback for image bytes
275
  try:
276
  h = requests.head(url, timeout=6, allow_redirects=True)
 
277
  ctype = (h.headers.get("content-type") or "").lower()
278
  if ctype.startswith("video/") or any(url.lower().split("?")[0].endswith(ext) for ext in VIDEO_EXTS):
279
  return None, url, "Video"
280
  except Exception:
281
  pass
282
  try:
 
283
  r = requests.get(url, timeout=15)
284
  r.raise_for_status()
285
  img = Image.open(BytesIO(r.content))
@@ -304,9 +309,15 @@ with gr.Blocks(title="Flux Multimodal (fixed)", css=css) as demo:
304
 
305
  def preview_update(url):
306
  img, vid, label = load_preview(url)
307
- return (img if label == "Image" else None, vid if label == "Video" else None, label == "Image", label == "Video")
 
 
 
308
 
309
- url_input.change(fn=preview_update, inputs=[url_input], outputs=[preview_image, preview_video, preview_image, preview_video])
 
 
 
310
 
311
  def submit_wrapper(url, prompt, key):
312
  return process_media(url, prompt, key)
 
1
  #!/usr/bin/env python3
2
+ # Single-file Gradio app: reliable preview, image->image model, video->video model or frame fallback,
3
+ # streaming disabled for safety; preserves default prompt text unchanged.
4
  import os
5
  import subprocess
6
  import tempfile
 
44
 
45
  def fetch_bytes(src: str, stream_threshold=STREAM_THRESHOLD, timeout=60) -> bytes:
46
  if is_remote(src):
47
+ # HEAD first to make preview/size decision; fallback to GET if HEAD fails
48
  try:
49
+ h = requests.head(src, timeout=6, allow_redirects=True)
50
  h.raise_for_status()
51
  cl = h.headers.get("content-length")
52
  if cl and int(cl) > stream_threshold:
 
64
  finally:
65
  try: os.remove(path)
66
  except Exception: pass
 
67
  except Exception:
68
  pass
69
  with requests.get(src, timeout=timeout) as r:
 
101
  def extract_best_frames_bytes(media_path: str, sample_count: int = 5, timeout_probe: int = 10, timeout_extract: int = 15) -> list:
102
  if not FFMPEG_BIN or not os.path.exists(media_path):
103
  return []
104
+ # Use ffprobe fallback if available; avoid unsupported flags
 
105
  try:
106
+ probe_cmd = [FFMPEG_BIN, "-v", "error", "-i", media_path, "-hide_banner"]
107
+ subprocess.run(probe_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=timeout_probe)
108
+ # best-effort timestamps if probing failed to get duration
109
+ # We'll still try a few timestamps
110
  except Exception:
111
+ pass
112
+ # generate timestamps heuristically
113
+ timestamps = [0.5, 1.0, 2.0][:sample_count]
 
 
114
  frames = []
115
  for i, t in enumerate(timestamps):
116
  fd, tmp = tempfile.mkstemp(suffix=f"_{i}.jpg")
117
  os.close(fd)
118
+ cmd = [FFMPEG_BIN, "-nostdin", "-y", "-ss", str(t), "-i", media_path, "-frames:v", "1", "-q:v", "2", tmp]
119
  try:
120
  subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=timeout_extract)
121
  if os.path.exists(tmp) and os.path.getsize(tmp) > 0:
 
156
 
157
  def extract_text_from_response(res, parts: list):
158
  try:
159
+ choices = getattr(res, "choices", None) or (res.get("choices") if isinstance(res, dict) else [])
160
  except Exception:
161
  choices = []
162
  if not choices:
163
  parts.append(str(res))
164
  return
165
  try:
166
+ first = choices[0]
167
+ msg = first.message if hasattr(first, "message") else first.get("message", first)
168
  if isinstance(msg, dict):
169
  content = msg.get("content")
170
  else:
 
211
  is_video = ext in VIDEO_EXTS
212
  if is_remote(src):
213
  try:
214
+ h = requests.head(src, timeout=6, allow_redirects=True)
215
+ h.raise_for_status()
216
  ctype = (h.headers.get("content-type") or "").lower()
217
  if ctype.startswith("video/"):
218
  is_video = True; is_image = False
 
261
  def load_preview(url: str):
262
  if not url:
263
  return None, None, ""
264
+ # Local file path handling
265
  if not is_remote(url) and os.path.exists(url):
266
  ext = ext_from_src(url)
267
  if ext in VIDEO_EXTS:
 
274
  return img.convert("RGB"), None, "Image"
275
  except Exception:
276
  return None, None, "Preview failed"
277
+ # Remote: HEAD then GET fallback; ensure returned types match Gradio Image/Video expectations
278
  try:
279
  h = requests.head(url, timeout=6, allow_redirects=True)
280
+ h.raise_for_status()
281
  ctype = (h.headers.get("content-type") or "").lower()
282
  if ctype.startswith("video/") or any(url.lower().split("?")[0].endswith(ext) for ext in VIDEO_EXTS):
283
  return None, url, "Video"
284
  except Exception:
285
  pass
286
  try:
287
+ # GET and try to open as image
288
  r = requests.get(url, timeout=15)
289
  r.raise_for_status()
290
  img = Image.open(BytesIO(r.content))
 
309
 
310
  def preview_update(url):
311
  img, vid, label = load_preview(url)
312
+ show_img = label == "Image"
313
+ show_vid = label == "Video"
314
+ # Return values in order matching outputs assigned below
315
+ return (img if show_img else None, vid if show_vid else None, show_img, show_vid)
316
 
317
+ # wire change: outputs must match component types exactly
318
+ url_input.change(fn=preview_update,
319
+ inputs=[url_input],
320
+ outputs=[preview_image, preview_video, preview_image, preview_video])
321
 
322
  def submit_wrapper(url, prompt, key):
323
  return process_media(url, prompt, key)