Hug0endob commited on
Commit
cdeafb3
·
verified ·
1 Parent(s): f532fe5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -45
app.py CHANGED
@@ -417,7 +417,7 @@ def create_demo():
417
  with gr.Column(scale=1):
418
  preview_image = gr.Image(label="Preview Image", type="pil", elem_classes="preview_media", visible=False)
419
  preview_video = gr.Video(label="Preview Video", elem_classes="preview_media", visible=False, format="mp4")
420
- preview_status = gr.Textbox(label="Preview status", interactive=False, lines=1, value="", visible=True)
421
  with gr.Column(scale=2):
422
  url_input = gr.Textbox(label="Image / Video URL", placeholder="https://...", lines=1)
423
  with gr.Accordion("Prompt (optional)", open=False):
@@ -431,43 +431,30 @@ def create_demo():
431
  output_md = gr.Markdown("")
432
  status_state = gr.State("idle")
433
 
434
- def _set_preview_text(text: str):
435
- return gr.update(value=text)
436
-
437
  def load_preview(url: str):
438
  if not url:
439
  return gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value="")
440
- # If remote and looks like a video by extension, show video immediately and try async conversion for browser compatibility
441
- if is_remote(url) and any(url.lower().endswith(ext) for ext in VIDEO_EXTS):
442
- return gr.update(value=None, visible=False), gr.update(value=url, visible=True), gr.update(value="Remote video detected — showing preview if browser-playable; converting if needed...")
443
- # Try fetching as image first (quick check). Provide verbose status messages.
444
  try:
445
  if is_remote(url):
446
  head = safe_head(url)
447
  if head:
448
  ctype = (head.headers.get("content-type") or "").lower()
449
- if ctype.startswith("video/"):
450
- return gr.update(value=None, visible=False), gr.update(value=url, visible=True), gr.update(value=f"Remote video (content-type={ctype}) showing preview if browser-playable.")
451
- if ctype.startswith("image/"):
452
- r = safe_get(url, timeout=10)
453
- img_bytes = r.content
454
- else:
455
- # try GET anyway
456
- r = safe_get(url, timeout=10)
457
- img_bytes = r.content
458
- else:
459
- r = safe_get(url, timeout=10)
460
- img_bytes = r.content
461
  else:
462
  with open(url, "rb") as f:
463
  img_bytes = f.read()
464
  img = Image.open(BytesIO(img_bytes))
465
  if getattr(img, "is_animated", False):
466
  img.seek(0)
467
- return gr.update(value=img.convert("RGB"), visible=True), gr.update(value=None, visible=False), gr.update(value="Image preview loaded")
468
  except Exception as e:
469
- # Fallback: if file might be video but extension missing, show helpful message
470
- msg = f"Preview load failed: {e}. If this is a video, ensure URL ends with a video extension or upload a playable mp4/webm."
471
  return gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value=msg)
472
 
473
  url_input.change(fn=load_preview, inputs=[url_input], outputs=[preview_image, preview_video, preview_status])
@@ -477,10 +464,9 @@ def create_demo():
477
 
478
  clear_btn.click(fn=clear_all, inputs=[], outputs=[url_input, preview_image, preview_video, status_state, progress_md, output_md])
479
 
480
- def _convert_video_for_preview(path: str, progress_cb=None) -> str:
481
  if not FFMPEG_BIN or not os.path.exists(path):
482
  return path
483
- # ensure mp4 with h264 for browser playability
484
  out_fd, out_path = tempfile.mkstemp(suffix=".mp4")
485
  os.close(out_fd)
486
  cmd = [
@@ -501,23 +487,19 @@ def create_demo():
501
  if not url:
502
  return ("error", "**Error:** No URL provided.")
503
  progress(0.01, desc="Starting processing...")
504
- # Fetch header to decide media type early for verbose feedback
505
  progress(0.03, desc="Checking URL / content-type...")
506
  is_img, is_vid = determine_media_type(url, progress=progress)
507
  progress(0.06, desc=f"Determined media type: image={is_img}, video={is_vid}")
 
508
  if is_vid:
509
- progress(0.08, desc="Fetching video bytes (this may take a while)...")
510
  raw = fetch_bytes(url, timeout=120, progress=progress)
511
  tmp = save_bytes_to_temp(raw, suffix=ext_from_src(url) or ".mp4")
512
- progress(0.15, desc="Saved video to temp file; preparing for preview/analysis...")
513
- # Convert for preview to ensure browser-playable format (non-destructive)
514
- try:
515
- preview_tmp = _convert_video_for_preview(tmp, progress_cb=progress)
516
- except Exception:
517
- preview_tmp = tmp
518
- # Update progress text for preview step (front-end preview will show converted file path)
519
- progress(0.25, desc="Video ready for preview and analysis. Starting analysis...")
520
- res = analyze_video_cohesive(get_client(key), tmp, prompt or "", progress=progress)
521
  progress(0.98, desc="Finalizing result...")
522
  try:
523
  if preview_tmp != tmp:
@@ -532,31 +514,31 @@ def create_demo():
532
  progress(0.08, desc="Fetching image bytes...")
533
  raw = fetch_bytes(url, progress=progress)
534
  progress(0.18, desc="Analyzing image...")
535
- res = analyze_image_structured(get_client(key), raw, prompt or "", progress=progress)
 
 
 
536
  progress(0.98, desc="Finalizing result...")
537
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
538
  return (status, res if isinstance(res, str) else str(res))
539
  else:
540
- # Unknown: try fetch and try image first, then video fallback
541
- progress(0.07, desc="Unknown media type — fetching bytes for heuristic check...")
542
  raw = fetch_bytes(url, timeout=120, progress=progress)
543
- # try image
544
  try:
545
  progress(0.15, desc="Attempting to interpret as image...")
546
- _ = Image.open(BytesIO(raw))
547
  progress(0.2, desc="Image detected — analyzing...")
548
- res = analyze_image_structured(get_client(key), raw, prompt or "", progress=progress)
549
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
550
  return (status, res if isinstance(res, str) else str(res))
551
  except Exception:
552
- # Treat as video
553
  fd, tmp = tempfile.mkstemp(suffix=ext_from_src(url) or ".mp4")
554
  os.close(fd)
555
  with open(tmp, "wb") as fh:
556
  fh.write(raw)
557
  try:
558
  progress(0.3, desc="Saved fallback video file; analyzing...")
559
- res = analyze_video_cohesive(get_client(key), tmp, prompt or "", progress=progress)
560
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
561
  return (status, res if isinstance(res, str) else str(res))
562
  finally:
@@ -572,7 +554,7 @@ def create_demo():
572
  return _btn_label_for_status(s)
573
 
574
  status_state.change(fn=btn_label_from_state, inputs=[status_state], outputs=[submit_btn])
575
- # Show verbose progress messages in progress_md by listening to a lightweight helper that maps state to text.
576
  def status_to_progress_text(s):
577
  return {"idle":"Idle","busy":"Processing…","done":"Completed","error":"Error — see output"}.get(s, s)
578
  status_state.change(fn=status_to_progress_text, inputs=[status_state], outputs=[progress_md])
 
417
  with gr.Column(scale=1):
418
  preview_image = gr.Image(label="Preview Image", type="pil", elem_classes="preview_media", visible=False)
419
  preview_video = gr.Video(label="Preview Video", elem_classes="preview_media", visible=False, format="mp4")
420
+ preview_status = gr.Textbox(label="Preview status", interactive=False, lines=2, value="", visible=True)
421
  with gr.Column(scale=2):
422
  url_input = gr.Textbox(label="Image / Video URL", placeholder="https://...", lines=1)
423
  with gr.Accordion("Prompt (optional)", open=False):
 
431
  output_md = gr.Markdown("")
432
  status_state = gr.State("idle")
433
 
 
 
 
434
  def load_preview(url: str):
435
  if not url:
436
  return gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value="")
437
+ # Quick content-type/extension heuristic first
 
 
 
438
  try:
439
  if is_remote(url):
440
  head = safe_head(url)
441
  if head:
442
  ctype = (head.headers.get("content-type") or "").lower()
443
+ if ctype.startswith("video/") or any(url.lower().endswith(ext) for ext in VIDEO_EXTS):
444
+ return gr.update(value=None, visible=False), gr.update(value=url, visible=True), gr.update(value=f"Remote video detected (content-type={ctype}). Showing preview if browser-playable; converting if necessary.")
445
+ # Try image fetch (fast)
446
+ if is_remote(url):
447
+ r = safe_get(url, timeout=10)
448
+ img_bytes = r.content
 
 
 
 
 
 
449
  else:
450
  with open(url, "rb") as f:
451
  img_bytes = f.read()
452
  img = Image.open(BytesIO(img_bytes))
453
  if getattr(img, "is_animated", False):
454
  img.seek(0)
455
+ return gr.update(value=img.convert("RGB"), visible=True), gr.update(value=None, visible=False), gr.update(value="Image preview loaded.")
456
  except Exception as e:
457
+ msg = f"Preview load failed: {e}. If this is a video, ensure URL ends with .mp4/.webm or upload a playable file."
 
458
  return gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value=msg)
459
 
460
  url_input.change(fn=load_preview, inputs=[url_input], outputs=[preview_image, preview_video, preview_status])
 
464
 
465
  clear_btn.click(fn=clear_all, inputs=[], outputs=[url_input, preview_image, preview_video, status_state, progress_md, output_md])
466
 
467
+ def _convert_video_for_preview(path: str) -> str:
468
  if not FFMPEG_BIN or not os.path.exists(path):
469
  return path
 
470
  out_fd, out_path = tempfile.mkstemp(suffix=".mp4")
471
  os.close(out_fd)
472
  cmd = [
 
487
  if not url:
488
  return ("error", "**Error:** No URL provided.")
489
  progress(0.01, desc="Starting processing...")
 
490
  progress(0.03, desc="Checking URL / content-type...")
491
  is_img, is_vid = determine_media_type(url, progress=progress)
492
  progress(0.06, desc=f"Determined media type: image={is_img}, video={is_vid}")
493
+ client = get_client(key)
494
  if is_vid:
495
+ progress(0.08, desc="Fetching video bytes (may take a while)...")
496
  raw = fetch_bytes(url, timeout=120, progress=progress)
497
  tmp = save_bytes_to_temp(raw, suffix=ext_from_src(url) or ".mp4")
498
+ progress(0.18, desc="Saved video to temp; converting for preview if needed...")
499
+ preview_tmp = _convert_video_for_preview(tmp)
500
+ # Return preview path to frontend by placing it into preview_video (separate event)
501
+ progress(0.25, desc="Starting video analysis...")
502
+ res = analyze_video_cohesive(client, tmp, prompt or "", progress=progress)
 
 
 
 
503
  progress(0.98, desc="Finalizing result...")
504
  try:
505
  if preview_tmp != tmp:
 
514
  progress(0.08, desc="Fetching image bytes...")
515
  raw = fetch_bytes(url, progress=progress)
516
  progress(0.18, desc="Analyzing image...")
517
+ try:
518
+ res = analyze_image_structured(client, raw, prompt or "", progress=progress)
519
+ except UnidentifiedImageError:
520
+ return ("error", "Error: provided file is not a valid image.")
521
  progress(0.98, desc="Finalizing result...")
522
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
523
  return (status, res if isinstance(res, str) else str(res))
524
  else:
525
+ progress(0.07, desc="Unknown media type fetching bytes for heuristics...")
 
526
  raw = fetch_bytes(url, timeout=120, progress=progress)
 
527
  try:
528
  progress(0.15, desc="Attempting to interpret as image...")
529
+ Image.open(BytesIO(raw))
530
  progress(0.2, desc="Image detected — analyzing...")
531
+ res = analyze_image_structured(client, raw, prompt or "", progress=progress)
532
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
533
  return (status, res if isinstance(res, str) else str(res))
534
  except Exception:
 
535
  fd, tmp = tempfile.mkstemp(suffix=ext_from_src(url) or ".mp4")
536
  os.close(fd)
537
  with open(tmp, "wb") as fh:
538
  fh.write(raw)
539
  try:
540
  progress(0.3, desc="Saved fallback video file; analyzing...")
541
+ res = analyze_video_cohesive(client, tmp, prompt or "", progress=progress)
542
  status = "done" if not (isinstance(res, str) and res.lower().startswith("error")) else "error"
543
  return (status, res if isinstance(res, str) else str(res))
544
  finally:
 
554
  return _btn_label_for_status(s)
555
 
556
  status_state.change(fn=btn_label_from_state, inputs=[status_state], outputs=[submit_btn])
557
+
558
  def status_to_progress_text(s):
559
  return {"idle":"Idle","busy":"Processing…","done":"Completed","error":"Error — see output"}.get(s, s)
560
  status_state.change(fn=status_to_progress_text, inputs=[status_state], outputs=[progress_md])