Michaelqaz commited on
Commit
a7a8de0
·
1 Parent(s): c0e7e4d

demo update

Browse files
.gitattributes CHANGED
@@ -41,3 +41,6 @@ examples/ai-valley.jpg filter=lfs diff=lfs merge=lfs -text
41
  examples/istock-motorbike-rice-field.jpg filter=lfs diff=lfs merge=lfs -text
42
  examples/omni-misty-forest.jpg filter=lfs diff=lfs merge=lfs -text
43
  examples/omni-horse-trail.jpg filter=lfs diff=lfs merge=lfs -text
 
 
 
 
41
  examples/istock-motorbike-rice-field.jpg filter=lfs diff=lfs merge=lfs -text
42
  examples/omni-misty-forest.jpg filter=lfs diff=lfs merge=lfs -text
43
  examples/omni-horse-trail.jpg filter=lfs diff=lfs merge=lfs -text
44
+ examples/omni-greek-square.jpg filter=lfs diff=lfs merge=lfs -text
45
+ examples/istock-country-road.jpg filter=lfs diff=lfs merge=lfs -text
46
+ examples/istock-skier.jpg filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -539,6 +539,32 @@ EXAMPLES = [
539
  "idyllic, with greenery and natural elements dominating the scene.",
540
  "orbit_left",
541
  ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  [
543
  str(HERE / "examples" / "ai-airmountains.jpg"),
544
  "A vast sky filled with multiple floating islands of different sizes, suspended above a "
@@ -592,6 +618,20 @@ CHARACTER_EXAMPLES = [
592
  ],
593
  ]
594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
  CSS = """
596
  #col-container { margin: 0 auto; max-width: 1180px; }
597
  .dark .gradio-container { color: var(--body-text-color); }
@@ -610,68 +650,62 @@ with gr.Blocks() as demo:
610
  Drop in an image, pick a camera move, and (optionally) describe the scene — you get
611
  an 81-frame, 832x480, 16 fps clip that follows that trajectory. Leave the description
612
  blank and a small vision-language model writes one from your image automatically.
 
 
 
 
613
  """
614
  )
615
  with gr.Row():
616
- with gr.Column(scale=1):
617
- image_input = gr.Image(
618
- label="First frame", type="filepath", height=300, sources=["upload", "clipboard"]
619
- )
620
- prompt_input = gr.Textbox(
621
- label="Scene description",
622
- placeholder="Describe what is in the image… (leave empty to auto-caption it)",
623
- lines=4,
624
- info="Optional — if left blank, Qwen2-VL writes a caption from your image.",
625
  )
626
- trajectory_input = gr.Dropdown(
627
- label="Camera move",
628
- choices=PRESETS,
629
- value="dolly_in",
630
- )
631
- run_button = gr.Button("Generate video", variant="primary")
632
- with gr.Column(scale=1):
633
- video_output = gr.Video(
634
- label="Generated video", autoplay=True, loop=True, height=300
635
- )
636
- path_preview = gr.Image(
637
- label="Camera path (start green, end red)",
638
- height=280,
639
- interactive=False,
640
- )
641
- status_output = gr.Markdown()
642
-
643
- gr.Examples(
644
- examples=EXAMPLES,
645
- inputs=[image_input, prompt_input, trajectory_input],
646
- outputs=[video_output, seed_input, status_output],
647
- fn=generate,
648
- cache_examples=True,
649
- cache_mode="lazy",
650
- label="Examples — click a row to load its image, prompt and camera move",
651
- examples_per_page=8,
652
- )
653
- gr.Examples(
654
- examples=CHARACTER_EXAMPLES,
655
- inputs=[image_input, prompt_input, trajectory_input],
656
- outputs=[video_output, seed_input, status_output],
657
- fn=generate,
658
- cache_examples=True,
659
- cache_mode="lazy",
660
- label="Examples with characters",
661
- examples_per_page=8,
662
- )
663
 
664
  with gr.Accordion("Advanced settings", open=False):
665
  with gr.Row():
666
  steps_input = gr.Slider(
667
  label="Sampling steps",
668
  minimum=4,
669
- maximum=8,
670
  step=1,
671
  value=4,
672
  info=(
673
  "The distillation LoRA is trained for 4 steps (2 high-noise + "
674
- "2 low-noise) — about 68s. Each extra step adds ~14s of GPU time."
 
675
  ),
676
  )
677
  motion_input = gr.Slider(
@@ -696,6 +730,27 @@ with gr.Blocks() as demo:
696
  )
697
  randomize_input = gr.Checkbox(label="Randomize seed", value=True)
698
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  gr.Markdown(
700
  """
701
  **Notes** · Camera paths are OpenCV camera-to-world matrices `[81, 3, 4]` relative to
@@ -709,6 +764,9 @@ with gr.Blocks() as demo:
709
  """
710
  )
711
 
 
 
 
712
  preview_inputs = [trajectory_input, motion_input]
713
  trajectory_input.change(preview_path, preview_inputs, path_preview, show_progress="hidden")
714
  motion_input.change(preview_path, preview_inputs, path_preview, show_progress="hidden")
 
539
  "idyllic, with greenery and natural elements dominating the scene.",
540
  "orbit_left",
541
  ],
542
+ [
543
+ str(HERE / "examples" / "omni-greek-square.jpg"),
544
+ "A lively ancient Greek market square with stone-paved pathways, wooden crates, and "
545
+ "fabric-draped stalls full of clay pottery. The setting features classical architecture, "
546
+ "including a prominent colonnaded building on the left and a vast cityscape stretching into "
547
+ "the distance. The clear weather and bright sunlight enhance the vividness of the scene, "
548
+ "creating a dynamic and immersive atmosphere.",
549
+ "crane_up_fwd",
550
+ ],
551
+ [
552
+ str(HERE / "examples" / "istock-country-road.jpg"),
553
+ "A white car driving on a winding road surrounded by lush green grass, seen from an aerial "
554
+ "perspective. The road is narrow and curves gently through the landscape. The grass on "
555
+ "either side is vibrant and well-maintained, with some patches of darker green. The overall "
556
+ "scene is serene and picturesque, with the car travelling through the greenery.",
557
+ "dolly_in",
558
+ ],
559
+ [
560
+ str(HERE / "examples" / "istock-skier.jpg"),
561
+ "A snowy mountain landscape under a clear blue sky. A person is skiing down a well-groomed "
562
+ "slope, leaving tracks in the snow. The skier is dressed in dark clothing and is using ski "
563
+ "poles for balance. In the background, there are snow-covered mountains with rocky "
564
+ "outcrops. A ski lift with red support towers is visible to the left, and a small building "
565
+ "is seen at the bottom of the slope.",
566
+ "orbit_left",
567
+ ],
568
  [
569
  str(HERE / "examples" / "ai-airmountains.jpg"),
570
  "A vast sky filled with multiple floating islands of different sizes, suspended above a "
 
618
  ],
619
  ]
620
 
621
+ # A compact image-only strip for the left rail — every showcase frame, in the same order.
622
+ # Clicking a thumbnail loads its image, prompt and camera move into the input boxes.
623
+ QUICK_PICKS = CHARACTER_EXAMPLES + EXAMPLES
624
+ QUICK_PICK_GALLERY = [
625
+ (row[0], Path(row[0]).stem.replace("istock-", "").replace("ai-", "").replace("omni-", "").replace("-", " "))
626
+ for row in QUICK_PICKS
627
+ ]
628
+
629
+
630
+ def load_quick_pick(event: gr.SelectData) -> tuple[str, str, str]:
631
+ image, prompt, trajectory = QUICK_PICKS[event.index]
632
+ return image, prompt, trajectory
633
+
634
+
635
  CSS = """
636
  #col-container { margin: 0 auto; max-width: 1180px; }
637
  .dark .gradio-container { color: var(--body-text-color); }
 
650
  Drop in an image, pick a camera move, and (optionally) describe the scene — you get
651
  an 81-frame, 832x480, 16 fps clip that follows that trajectory. Leave the description
652
  blank and a small vision-language model writes one from your image automatically.
653
+
654
+ *To fit a ZeroGPU slot this Space uses a fast few-step, fp8 setting, which can
655
+ slightly soften quality; for the highest-fidelity results you're welcome to use the
656
+ full [reference code](https://github.com/TencentARC/SCoPE).*
657
  """
658
  )
659
  with gr.Row():
660
+ with gr.Column(scale=1, min_width=110):
661
+ quick_picks = gr.Gallery(
662
+ value=QUICK_PICK_GALLERY,
663
+ label="Quick picks — click to load",
664
+ columns=1,
665
+ height=600,
666
+ object_fit="cover",
667
+ allow_preview=False,
 
668
  )
669
+ with gr.Column(scale=5):
670
+ with gr.Row():
671
+ with gr.Column(scale=1):
672
+ image_input = gr.Image(
673
+ label="First frame", type="filepath", height=300,
674
+ sources=["upload", "clipboard"],
675
+ )
676
+ prompt_input = gr.Textbox(
677
+ label="Scene description",
678
+ placeholder="Describe what is in the image… (leave empty to auto-caption it)",
679
+ lines=4,
680
+ info="Optional if left blank, Qwen2-VL writes a caption from your image.",
681
+ )
682
+ trajectory_input = gr.Dropdown(
683
+ label="Camera move", choices=PRESETS, value="dolly_in",
684
+ )
685
+ run_button = gr.Button("Generate video", variant="primary")
686
+ with gr.Column(scale=1):
687
+ video_output = gr.Video(
688
+ label="Generated video", autoplay=True, loop=True, height=300
689
+ )
690
+ path_preview = gr.Image(
691
+ label="Camera path (start green, end red)",
692
+ height=280,
693
+ interactive=False,
694
+ )
695
+ status_output = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
696
 
697
  with gr.Accordion("Advanced settings", open=False):
698
  with gr.Row():
699
  steps_input = gr.Slider(
700
  label="Sampling steps",
701
  minimum=4,
702
+ maximum=16,
703
  step=1,
704
  value=4,
705
  info=(
706
  "The distillation LoRA is trained for 4 steps (2 high-noise + "
707
+ "2 low-noise) — about 68s. Each extra step adds ~14s of GPU time; "
708
+ "gains past ~8 steps are marginal for the distilled LoRA."
709
  ),
710
  )
711
  motion_input = gr.Slider(
 
730
  )
731
  randomize_input = gr.Checkbox(label="Randomize seed", value=True)
732
 
733
+ gr.Examples(
734
+ examples=CHARACTER_EXAMPLES,
735
+ inputs=[image_input, prompt_input, trajectory_input],
736
+ outputs=[video_output, seed_input, status_output],
737
+ fn=generate,
738
+ cache_examples=True,
739
+ cache_mode="lazy",
740
+ label="Camera control with people in the scene — click a row to load it",
741
+ examples_per_page=8,
742
+ )
743
+ gr.Examples(
744
+ examples=EXAMPLES,
745
+ inputs=[image_input, prompt_input, trajectory_input],
746
+ outputs=[video_output, seed_input, status_output],
747
+ fn=generate,
748
+ cache_examples=True,
749
+ cache_mode="lazy",
750
+ label="More examples — click a row to load its image, prompt and camera move",
751
+ examples_per_page=8,
752
+ )
753
+
754
  gr.Markdown(
755
  """
756
  **Notes** · Camera paths are OpenCV camera-to-world matrices `[81, 3, 4]` relative to
 
764
  """
765
  )
766
 
767
+ quick_picks.select(
768
+ load_quick_pick, None, [image_input, prompt_input, trajectory_input], show_progress="hidden"
769
+ )
770
  preview_inputs = [trajectory_input, motion_input]
771
  trajectory_input.change(preview_path, preview_inputs, path_preview, show_progress="hidden")
772
  motion_input.change(preview_path, preview_inputs, path_preview, show_progress="hidden")
examples/istock-country-road.jpg ADDED

Git LFS Details

  • SHA256: 9e886551584c02744c24b455f9f0de95a35d00e54964bf5184a3bd2a43bc2acc
  • Pointer size: 131 Bytes
  • Size of remote file: 246 kB
examples/istock-skier.jpg ADDED

Git LFS Details

  • SHA256: 341c3874f29743da365d770ba1cb3a0140ce433cca15f2f69c8399f173032e21
  • Pointer size: 131 Bytes
  • Size of remote file: 138 kB
examples/omni-greek-square.jpg ADDED

Git LFS Details

  • SHA256: ddd1bd2f76ee517313966f7a74bcaee7c6e9015e9173d9520400454800399c8e
  • Pointer size: 131 Bytes
  • Size of remote file: 364 kB