Hug0endob commited on
Commit
375cc14
·
verified ·
1 Parent(s): bebf085

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -124
app.py CHANGED
@@ -581,132 +581,132 @@ def create_demo():
581
  return False
582
 
583
  # --- Convert only if not browser-playable
584
- def _convert_video_for_preview_if_needed(path: str) -> str:
585
- """
586
- Return a path that the Gradio video component can play.
587
- If the original file is already MP4 with H.264 (or another browser‑compatible codec),
588
- the original path is returned unchanged.
589
- Otherwise the file is re‑encoded to MP4 (H.264 + AAC) and the new path is returned.
590
- """
591
- if not FFMPEG_BIN or not os.path.exists(path):
592
- return path
593
-
594
- # Quick check: extension + ffprobe for codecs
595
- if path.lower().endswith((".mp4", ".m4v", ".mov")):
596
- info = _ffprobe_streams(path)
597
- if info:
598
- codecs = {s.get("codec_name") for s in info.get("streams", []) if s.get("codec_type") == "video"}
599
- if "h264" in codecs or "h265" in codecs:
600
- return path # already playable
601
-
602
- # Need conversion → write to a new temp MP4
603
- out_fd, out_path = tempfile.mkstemp(suffix=".mp4")
604
- os.close(out_fd)
605
- cmd = [
606
- FFMPEG_BIN, "-y", "-i", path,
607
- "-c:v", "libx264", "-preset", "veryfast", "-crf", "28",
608
- "-c:a", "aac", "-movflags", "+faststart", out_path,
609
- ]
610
- try:
611
- subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60)
612
- return out_path
613
- except Exception:
614
- # If conversion fails, fall back to the original (Gradio will show its own warning)
615
- try: os.remove(out_path)
616
- except Exception: pass
617
- return path
618
 
619
- def worker(url: str, prompt: str, key: str, progress=gr.Progress()):
620
- """Return (status, markdown_output, preview_path)."""
621
- try:
622
- if not url:
623
- return "error", "**Error:** No URL provided.", ""
624
-
625
- # ------------------------------------------------------------------
626
- # 1️⃣ Determine media type – use a *single* call to avoid duplicate work
627
- # ------------------------------------------------------------------
628
- progress(0.02, desc="Checking URL / content‑type")
629
- is_img, is_vid = determine_media_type(url, progress=progress)
630
-
631
- client = get_client(key)
632
- preview_path = ""
633
-
634
- # ------------------------------------------------------------------
635
- # 2️⃣ Helper to write a temp file with a *correct* suffix
636
- # ------------------------------------------------------------------
637
- def _temp_file(data: bytes, suffix: str) -> str:
638
- fd, p = tempfile.mkstemp(suffix=suffix)
639
- os.close(fd)
640
- with open(p, "wb") as f:
641
- f.write(data)
642
- return p
643
-
644
- # ------------------------------------------------------------------
645
- # 3️⃣ VIDEO PATH
646
- # ------------------------------------------------------------------
647
- if is_vid:
648
- progress(0.05, desc="Downloading video")
649
- raw = fetch_bytes(url, timeout=120, progress=progress)
650
- if not raw:
651
- return "error", "Failed to download video bytes.", ""
652
-
653
- # write with a proper video extension
654
- tmp_video = _temp_file(raw, suffix=ext_from_src(url) or ".mp4")
655
- progress(0.15, desc="Preparing preview")
656
- preview_path = _convert_video_for_preview_if_needed(tmp_video)
657
-
658
- progress(0.25, desc="Running full‑video analysis")
659
- result = analyze_video_cohesive(client, tmp_video, prompt, progress=progress)
660
-
661
- # clean‑up the *raw* temp file (preview may be a different file)
662
- try: os.remove(tmp_video)
663
- except Exception: pass
664
-
665
- # ------------------------------------------------------------------
666
- # 4️⃣ IMAGE PATH
667
- # ------------------------------------------------------------------
668
- elif is_img:
669
- progress(0.05, desc="Downloading image")
670
- raw = fetch_bytes(url, progress=progress)
671
-
672
- # preview image (always JPEG for consistency)
673
- preview_path = _temp_file(convert_to_jpeg_bytes(raw, base_h=1024), suffix=".jpg")
674
-
675
- progress(0.20, desc="Running image analysis")
676
- result = analyze_image_structured(client, raw, prompt, progress=progress)
677
-
678
- # ------------------------------------------------------------------
679
- # 5️⃣ FALLBACK – try image first, then video
680
- # ------------------------------------------------------------------
681
- else:
682
- progress(0.07, desc="Downloading unknown media")
683
- raw = fetch_bytes(url, timeout=120, progress=progress)
684
-
685
- # try to open as image
686
  try:
687
- Image.open(BytesIO(raw)).verify()
688
- is_img = True
689
  except Exception:
690
- is_img = False
691
-
692
- if is_img:
693
- preview_path = _temp_file(convert_to_jpeg_bytes(raw, base_h=1024), suffix=".jpg")
694
- result = analyze_image_structured(client, raw, prompt, progress=progress)
695
- else:
696
- tmp_vid = _temp_file(raw, suffix=ext_from_src(url) or ".mp4")
697
- preview_path = _convert_video_for_preview_if_needed(tmp_vid)
698
- result = analyze_video_cohesive(client, tmp_vid, prompt, progress=progress)
699
- try: os.remove(tmp_vid)
700
  except Exception: pass
701
-
702
- # ------------------------------------------------------------------
703
- # 6️⃣ Final status
704
- # ------------------------------------------------------------------
705
- status = "done" if not (isinstance(result, str) and result.lower().startswith("error")) else "error"
706
- return status, result if isinstance(result, str) else str(result), preview_path or ""
707
-
708
- except Exception as exc:
709
- return "error", f"Unexpected worker error: {exc}", ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
710
 
711
  def _start_processing(url, prompt, key):
712
  # set state to busy and launch the worker in the same call
@@ -770,8 +770,7 @@ def worker(url: str, prompt: str, key: str, progress=gr.Progress()):
770
 
771
  preview_path_state.change(fn=apply_preview, inputs=[preview_path_state], outputs=[preview_image, preview_video, preview_status])
772
 
773
- # ensure global queue behavior
774
- demo.queue()
775
  return demo
776
 
777
  if __name__ == "__main__":
 
581
  return False
582
 
583
  # --- Convert only if not browser-playable
584
+ def _convert_video_for_preview_if_needed(path: str) -> str:
585
+ """
586
+ Return a path that the Gradio video component can play.
587
+ If the original file is already MP4 with H.264 (or another browser‑compatible codec),
588
+ the original path is returned unchanged.
589
+ Otherwise the file is re‑encoded to MP4 (H.264 + AAC) and the new path is returned.
590
+ """
591
+ if not FFMPEG_BIN or not os.path.exists(path):
592
+ return path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
 
594
+ # Quick check: extension + ffprobe for codecs
595
+ if path.lower().endswith((".mp4", ".m4v", ".mov")):
596
+ info = _ffprobe_streams(path)
597
+ if info:
598
+ codecs = {s.get("codec_name") for s in info.get("streams", []) if s.get("codec_type") == "video"}
599
+ if "h264" in codecs or "h265" in codecs:
600
+ return path # already playable
601
+
602
+ # Need conversion → write to a new temp MP4
603
+ out_fd, out_path = tempfile.mkstemp(suffix=".mp4")
604
+ os.close(out_fd)
605
+ cmd = [
606
+ FFMPEG_BIN, "-y", "-i", path,
607
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "28",
608
+ "-c:a", "aac", "-movflags", "+faststart", out_path,
609
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  try:
611
+ subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60)
612
+ return out_path
613
  except Exception:
614
+ # If conversion fails, fall back to the original (Gradio will show its own warning)
615
+ try: os.remove(out_path)
 
 
 
 
 
 
 
 
616
  except Exception: pass
617
+ return path
618
+
619
+ def worker(url: str, prompt: str, key: str, progress=gr.Progress()):
620
+ """Return (status, markdown_output, preview_path)."""
621
+ try:
622
+ if not url:
623
+ return "error", "**Error:** No URL provided.", ""
624
+
625
+ # ------------------------------------------------------------------
626
+ # 1️⃣ Determine media type – use a *single* call to avoid duplicate work
627
+ # ------------------------------------------------------------------
628
+ progress(0.02, desc="Checking URL / content‑type")
629
+ is_img, is_vid = determine_media_type(url, progress=progress)
630
+
631
+ client = get_client(key)
632
+ preview_path = ""
633
+
634
+ # ------------------------------------------------------------------
635
+ # 2️⃣ Helper to write a temp file with a *correct* suffix
636
+ # ------------------------------------------------------------------
637
+ def _temp_file(data: bytes, suffix: str) -> str:
638
+ fd, p = tempfile.mkstemp(suffix=suffix)
639
+ os.close(fd)
640
+ with open(p, "wb") as f:
641
+ f.write(data)
642
+ return p
643
+
644
+ # ------------------------------------------------------------------
645
+ # 3️⃣ VIDEO PATH
646
+ # ------------------------------------------------------------------
647
+ if is_vid:
648
+ progress(0.05, desc="Downloading video")
649
+ raw = fetch_bytes(url, timeout=120, progress=progress)
650
+ if not raw:
651
+ return "error", "Failed to download video bytes.", ""
652
+
653
+ # write with a proper video extension
654
+ tmp_video = _temp_file(raw, suffix=ext_from_src(url) or ".mp4")
655
+ progress(0.15, desc="Preparing preview")
656
+ preview_path = _convert_video_for_preview_if_needed(tmp_video)
657
+
658
+ progress(0.25, desc="Running full‑video analysis")
659
+ result = analyze_video_cohesive(client, tmp_video, prompt, progress=progress)
660
+
661
+ # clean‑up the *raw* temp file (preview may be a different file)
662
+ try: os.remove(tmp_video)
663
+ except Exception: pass
664
+
665
+ # ------------------------------------------------------------------
666
+ # 4️⃣ IMAGE PATH
667
+ # ------------------------------------------------------------------
668
+ elif is_img:
669
+ progress(0.05, desc="Downloading image")
670
+ raw = fetch_bytes(url, progress=progress)
671
+
672
+ # preview image (always JPEG for consistency)
673
+ preview_path = _temp_file(convert_to_jpeg_bytes(raw, base_h=1024), suffix=".jpg")
674
+
675
+ progress(0.20, desc="Running image analysis")
676
+ result = analyze_image_structured(client, raw, prompt, progress=progress)
677
+
678
+ # ------------------------------------------------------------------
679
+ # 5️⃣ FALLBACK – try image first, then video
680
+ # ------------------------------------------------------------------
681
+ else:
682
+ progress(0.07, desc="Downloading unknown media")
683
+ raw = fetch_bytes(url, timeout=120, progress=progress)
684
+
685
+ # try to open as image
686
+ try:
687
+ Image.open(BytesIO(raw)).verify()
688
+ is_img = True
689
+ except Exception:
690
+ is_img = False
691
+
692
+ if is_img:
693
+ preview_path = _temp_file(convert_to_jpeg_bytes(raw, base_h=1024), suffix=".jpg")
694
+ result = analyze_image_structured(client, raw, prompt, progress=progress)
695
+ else:
696
+ tmp_vid = _temp_file(raw, suffix=ext_from_src(url) or ".mp4")
697
+ preview_path = _convert_video_for_preview_if_needed(tmp_vid)
698
+ result = analyze_video_cohesive(client, tmp_vid, prompt, progress=progress)
699
+ try: os.remove(tmp_vid)
700
+ except Exception: pass
701
+
702
+ # ------------------------------------------------------------------
703
+ # 6️⃣ Final status
704
+ # ------------------------------------------------------------------
705
+ status = "done" if not (isinstance(result, str) and result.lower().startswith("error")) else "error"
706
+ return status, result if isinstance(result, str) else str(result), preview_path or ""
707
+
708
+ except Exception as exc:
709
+ return "error", f"Unexpected worker error: {exc}", ""
710
 
711
  def _start_processing(url, prompt, key):
712
  # set state to busy and launch the worker in the same call
 
770
 
771
  preview_path_state.change(fn=apply_preview, inputs=[preview_path_state], outputs=[preview_image, preview_video, preview_status])
772
 
773
+ demo.queue()
 
774
  return demo
775
 
776
  if __name__ == "__main__":