Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -42,22 +42,31 @@ 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 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
| 48 |
if cl and int(cl) > stream_threshold:
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
return r.content
|
| 62 |
with open(src, "rb") as f:
|
| 63 |
return f.read()
|
|
@@ -98,12 +107,10 @@ def extract_best_frames_bytes(media_path: str, sample_count: int = 5, timeout_pr
|
|
| 98 |
duration = float(out) if out else None
|
| 99 |
except Exception:
|
| 100 |
duration = None
|
| 101 |
-
|
| 102 |
if duration and duration > 0:
|
| 103 |
timestamps = [(duration * i) / (sample_count + 1) for i in range(1, sample_count + 1)]
|
| 104 |
else:
|
| 105 |
timestamps = [0.5, 1.0, 2.0][:sample_count]
|
| 106 |
-
|
| 107 |
frames = []
|
| 108 |
for i, t in enumerate(timestamps):
|
| 109 |
fd, tmp = tempfile.mkstemp(suffix=f"_{i}.jpg")
|
|
@@ -259,15 +266,21 @@ def load_preview(url: str):
|
|
| 259 |
if ext in IMAGE_EXTS:
|
| 260 |
try:
|
| 261 |
img = Image.open(url)
|
|
|
|
|
|
|
| 262 |
return img.convert("RGB"), None, "Image"
|
| 263 |
except Exception:
|
| 264 |
return None, None, "Preview failed"
|
|
|
|
| 265 |
try:
|
| 266 |
-
h = requests.head(url, timeout=
|
| 267 |
ctype = (h.headers.get("content-type") or "").lower()
|
| 268 |
if ctype.startswith("video/") or any(url.lower().split("?")[0].endswith(ext) for ext in VIDEO_EXTS):
|
| 269 |
return None, url, "Video"
|
| 270 |
-
|
|
|
|
|
|
|
|
|
|
| 271 |
r.raise_for_status()
|
| 272 |
img = Image.open(BytesIO(r.content))
|
| 273 |
if getattr(img, "is_animated", False):
|
|
@@ -294,7 +307,11 @@ with gr.Blocks(title="Flux Multimodal (fixed)", css=css) as demo:
|
|
| 294 |
return (img if label == "Image" else None, vid if label == "Video" else None, label == "Image", label == "Video")
|
| 295 |
|
| 296 |
url_input.change(fn=preview_update, inputs=[url_input], outputs=[preview_image, preview_video, preview_image, preview_video])
|
| 297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
|
| 299 |
if __name__ == "__main__":
|
| 300 |
demo.queue().launch()
|
|
|
|
| 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:
|
| 51 |
+
with requests.get(src, timeout=timeout, stream=True) as r:
|
| 52 |
+
r.raise_for_status()
|
| 53 |
+
fd, path = tempfile.mkstemp()
|
| 54 |
+
os.close(fd)
|
| 55 |
+
try:
|
| 56 |
+
with open(path, "wb") as f:
|
| 57 |
+
for chunk in r.iter_content(8192):
|
| 58 |
+
if chunk:
|
| 59 |
+
f.write(chunk)
|
| 60 |
+
with open(path, "rb") as f:
|
| 61 |
+
return f.read()
|
| 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:
|
| 69 |
+
r.raise_for_status()
|
| 70 |
return r.content
|
| 71 |
with open(src, "rb") as f:
|
| 72 |
return f.read()
|
|
|
|
| 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")
|
|
|
|
| 266 |
if ext in IMAGE_EXTS:
|
| 267 |
try:
|
| 268 |
img = Image.open(url)
|
| 269 |
+
if getattr(img, "is_animated", False):
|
| 270 |
+
img.seek(0)
|
| 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))
|
| 286 |
if getattr(img, "is_animated", False):
|
|
|
|
| 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)
|
| 313 |
+
|
| 314 |
+
submit_btn.click(fn=submit_wrapper, inputs=[url_input, custom_prompt, api_key], outputs=[final_md])
|
| 315 |
|
| 316 |
if __name__ == "__main__":
|
| 317 |
demo.queue().launch()
|