alexnasa commited on
Commit
d900911
·
verified ·
1 Parent(s): 72ca150

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +184 -205
app.py CHANGED
@@ -637,27 +637,53 @@ class PromptBox(gr.HTML):
637
 
638
  class CameraDropdown(gr.HTML):
639
  """
640
- Custom dropdown (More-style).
641
- Outputs: selected option string, e.g. "Slide Left"
 
 
 
 
 
 
642
  """
643
- def __init__(self, choices, value="None", title="Camera LoRA", **kwargs):
644
  if not choices:
645
  raise ValueError("CameraDropdown requires choices.")
646
 
 
 
 
 
 
 
 
 
 
 
 
 
647
  uid = uuid.uuid4().hex[:8]
648
- safe_choices = [str(c) for c in choices]
649
 
650
- items_html = "\n".join(
651
- f"""<button type="button" class="cd-item" data-value="{c}">{c}</button>"""
652
- for c in safe_choices
653
- )
 
 
 
 
 
 
 
 
654
 
655
  html_template = f"""
656
  <div class="cd-wrap" data-cd="{uid}">
657
- <button type="button" class="cd-trigger" aria-haspopup="menu" aria-expanded="false">
658
- <span class="cd-trigger-text">More</span>
659
- <span class="cd-caret">▾</span>
660
- </button>
 
661
 
662
  <div class="cd-menu" role="menu" aria-hidden="true">
663
  <div class="cd-title">{title}</div>
@@ -668,94 +694,108 @@ class CameraDropdown(gr.HTML):
668
  </div>
669
  """
670
 
 
 
 
 
 
671
  js_on_load = r"""
672
  (() => {
673
- const wrap = element.querySelector(".cd-wrap");
674
- const trigger = element.querySelector(".cd-trigger");
675
- const triggerText = element.querySelector(".cd-trigger-text");
676
- const menu = element.querySelector(".cd-menu");
677
- const items = Array.from(element.querySelectorAll(".cd-item"));
 
 
 
 
 
 
 
 
678
 
679
- if (!wrap || !trigger || !menu || !items.length) return;
680
 
681
- function closeMenu() {
682
  menu.classList.remove("open");
683
  trigger.setAttribute("aria-expanded", "false");
684
  menu.setAttribute("aria-hidden", "true");
685
- }
686
 
687
- function openMenu() {
688
  menu.classList.add("open");
689
  trigger.setAttribute("aria-expanded", "true");
690
  menu.setAttribute("aria-hidden", "false");
691
- }
692
 
693
- function setValue(val, shouldTrigger = false) {
694
- const v = (val ?? "None");
695
- props.value = v;
696
- triggerText.textContent = v;
697
-
698
- // mark selected (for CSS tick)
699
- items.forEach(btn => {
700
- btn.dataset.selected = (btn.dataset.value === v) ? "true" : "false";
701
- });
702
-
703
- if (shouldTrigger) trigger("change", props.value);
704
- }
705
 
706
- // Toggle menu
707
- trigger.addEventListener("pointerdown", (e) => {
708
- e.preventDefault(); // prevents focus/blur weirdness
 
 
 
 
 
 
 
709
  e.stopPropagation();
710
  if (menu.classList.contains("open")) closeMenu();
711
  else openMenu();
712
- });
713
 
714
- // Close on outside interaction (use capture so it wins)
715
- document.addEventListener("pointerdown", (e) => {
716
  if (!wrap.contains(e.target)) closeMenu();
717
- }, true);
718
 
719
- // Close on ESC
720
- document.addEventListener("keydown", (e) => {
721
  if (e.key === "Escape") closeMenu();
722
- });
723
 
724
- // Close when focus leaves the dropdown (keyboard users)
725
- wrap.addEventListener("focusout", (e) => {
726
- // if the newly-focused element isn't inside wrap, close
727
  if (!wrap.contains(e.relatedTarget)) closeMenu();
728
- });
729
 
730
- // Item selection: use pointerdown so it closes immediately
731
- items.forEach((btn) => {
732
  btn.addEventListener("pointerdown", (e) => {
733
- e.preventDefault();
734
- e.stopPropagation();
735
-
736
- // close first so it never "sticks" open
737
- closeMenu();
738
- setValue(btn.dataset.value, true);
739
  });
740
- });
741
 
742
- // init
743
- setValue((props.value ?? "None"), false);
744
 
745
- // sync from Python updates
746
- let last = props.value;
747
- const syncFromProps = () => {
748
  if (props.value !== last) {
749
- last = props.value;
750
- setValue(last, false);
751
  }
752
  requestAnimationFrame(syncFromProps);
753
- };
754
- requestAnimationFrame(syncFromProps);
755
  })();
756
-
757
  """
758
 
 
 
 
 
 
759
  super().__init__(
760
  value=value,
761
  html_template=html_template,
@@ -763,47 +803,7 @@ class CameraDropdown(gr.HTML):
763
  **kwargs
764
  )
765
 
766
-
767
- def generate_video_example(input_image, prompt, camera_lora, resolution, progress=gr.Progress(track_tqdm=True)):
768
-
769
- w, h = apply_resolution(resolution)
770
-
771
- output_video = generate_video(
772
- input_image,
773
- prompt,
774
- 10, # duration seconds
775
- True, # enhance_prompt
776
- 42, # seed
777
- True, # randomize_seed
778
- h, # height
779
- w, # width
780
- camera_lora,
781
- None,
782
- progress
783
- )
784
-
785
- return output_video
786
-
787
- def generate_video_example_t2v(prompt, camera_lora, resolution, progress=gr.Progress(track_tqdm=True)):
788
-
789
- w, h = apply_resolution(resolution)
790
-
791
- output_video = generate_video(
792
- None,
793
- prompt,
794
- 15, # duration seconds
795
- True, # enhance_prompt
796
- 42, # seed
797
- True, # randomize_seed
798
- h, # height
799
- w, # width
800
- camera_lora,
801
- None,
802
- progress
803
- )
804
- return output_video
805
-
806
- def generate_video_example_s2v(input_image, prompt, camera_lora, resolution, audio_path, progress=gr.Progress(track_tqdm=True)):
807
 
808
  w, h = apply_resolution(resolution)
809
 
@@ -1123,6 +1123,23 @@ css = """
1123
  }
1124
  """
1125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1126
  css += """
1127
  /* ---- radioanimated ---- */
1128
  .ra-wrap{
@@ -1170,6 +1187,18 @@ css += """
1170
  }
1171
  """
1172
 
 
 
 
 
 
 
 
 
 
 
 
 
1173
  css += """
1174
  /* --- prompt box --- */
1175
  .ds-prompt{
@@ -1371,6 +1400,26 @@ css += """
1371
 
1372
  """
1373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1374
 
1375
 
1376
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
@@ -1465,12 +1514,30 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
1465
  visible=False
1466
  )
1467
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1468
  radioanimated_resolution = CameraDropdown(
1469
- choices=["16:9", "1:1", "9:16"],
 
 
 
 
1470
  value="16:9",
1471
  title="Resolution",
1472
  elem_id="radioanimated_resolution"
1473
  )
 
1474
 
1475
  width = gr.Number(label="Width", value=DEFAULT_1_STAGE_WIDTH, precision=0, visible=False)
1476
  height = gr.Number(label="Height", value=DEFAULT_1_STAGE_HEIGHT, precision=0, visible=False)
@@ -1492,28 +1559,6 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
1492
 
1493
  generate_btn = gr.Button("🤩 Generate Video", variant="primary", elem_classes="button-gradient")
1494
 
1495
- # with gr.Sidebar(width=280):
1496
- # gr.Examples(
1497
- # examples=[
1498
- # [
1499
- # "The video opens on a cake. A knife, held by a hand, is coming into frame and hovering over the cake. The knife then begins cutting into the cake to c4k3 cakeify it. As the knife slices the cake open, the inside of the cake is revealed to be cake with chocolate layers. The knife cuts through and the contents of the cake are revealed. Greek music playing in the background.",
1500
- # "Cakify",
1501
- # ],
1502
-
1503
- # [
1504
- # "The video showcases an item. The camera zooms out. Then infl4t3 inflates it, the item expanding into giant, inflated balloon against the landscape.",
1505
- # "Inflate",
1506
- # ],
1507
-
1508
- # [
1509
- # "The video begins with an item. A hydraulic press positioned above slowly descends towards the item. Upon contact, the hydraulic press c5us4 crushes it, deforming and flattening the item, causing the item to collapse inward until the item is no longer recognizable.",
1510
- # "Hydraulic",
1511
- # ],
1512
- # ],
1513
- # inputs=[prompt_ui, camera_lora_ui],
1514
- # label="Example",
1515
- # cache_examples=False,
1516
- # )
1517
  camera_lora_ui.change(
1518
  fn=lambda x: x,
1519
  inputs=camera_lora_ui,
@@ -1558,35 +1603,9 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
1558
  outputs=[output_video]
1559
  )
1560
 
1561
-
1562
-
1563
- timestep_prompt = """Style: Realistic live-action, cinematic, shallow depth of field, 24 fps, natural and dramatic lighting
1564
-
1565
- Environment: Interior of a space station module or realistic mock-up, metal panels, blinking lights, Earth visible through a large window
1566
-
1567
- Character:
1568
-
1569
- Woman: mid-30s, athletic build, wearing authentic-style futuristic space suit (real materials, fabric details, visible patches); calm, confident, precise movements; hair tucked or braided; expressive eyes visible through visor, reflecting focus and awe
1570
-
1571
- Timestamps & action sequence:
1572
-
1573
- 0:00–0:05 — Close-up on her face through visor; soft reflections of Earth and panels in her eyes; she adjusts her gloves and glances around, calm and focused.
1574
-
1575
- 0:05–0:10 — Medium shot; she moves to the large window, gazes out as the sun begins to rise over Earth’s horizon; her expression shifts slightly, squinting at the bright sunlight.
1576
-
1577
- 0:10–0:15 — Close-up on her face; she squints, shading her eyes with a gloved hand, mutters with dry humor: “Damn thing is blinding.” Camera captures Earth glowing in the background with cinematic lens flare across the window edge.
1578
-
1579
- Audio:
1580
-
1581
- Woman: calm, soft-spoken, slight dry humor, low tone
1582
-
1583
- Environment: soft hum of space station, faint beeps from panels
1584
-
1585
- Music: subtle cinematic synth or ambient pad, futuristic and minimal, emphasizing awe and solitude"""
1586
-
1587
  gr.Examples(
1588
  examples=[
1589
-
1590
  [
1591
  "supergirl-2.png",
1592
  "A fuzzy puppet superhero character resembling a female puppet with blonde hair and a blue superhero suit sleeping in bed and just waking up, she gradually gets up, rubbing her eyes and looking at her dog that just popped on the bed. the scene feels chaotic, comedic, and emotional with expressive puppet reactions, cinematic lighting, smooth camera motion, shallow depth of field, and high-quality puppet-style animation",
@@ -1594,79 +1613,39 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
1594
  "16:9",
1595
  "supergirl.m4a"
1596
  ],
1597
-
1598
- ],
1599
- fn=generate_video_example_s2v,
1600
- inputs=[input_image, prompt_ui, camera_lora_ui, radioanimated_resolution, audio_input],
1601
- outputs = [output_video],
1602
- label="S2V Example",
1603
- cache_examples=True,
1604
- )
1605
-
1606
- gr.Examples(
1607
- examples=[
1608
-
1609
- [
1610
- timestep_prompt,
1611
- "No LoRA",
1612
- "16:9",
1613
- ],
1614
-
1615
- ],
1616
- fn=generate_video_example_t2v,
1617
- inputs=[prompt_ui, camera_lora_ui, radioanimated_resolution],
1618
- outputs = [output_video],
1619
- label="T2V Example",
1620
- cache_examples=True,
1621
- )
1622
-
1623
-
1624
- # Add example
1625
- gr.Examples(
1626
- examples=[
1627
  [
1628
  "supergirl.png",
1629
  "A fuzzy puppet superhero character resembling a female puppet with blonde hair and a blue superhero suit stands inside an icy cave made of frozen walls and icicles, she looks panicked and frantic, rapidly turning her head left and right and scanning the cave while waving her arms and shouting angrily and desperately, mouthing the words “where the hell is my dog,” her movements exaggerated and puppet-like with high energy and urgency, suddenly a second puppet dog bursts into frame from the side, jumping up excitedly and tackling her affectionately while licking her face repeatedly, she freezes in surprise and then breaks into relief and laughter as the dog continues licking her, the scene feels chaotic, comedic, and emotional with expressive puppet reactions, cinematic lighting, smooth camera motion, shallow depth of field, and high-quality puppet-style animation",
1630
- "Detailer",
1631
  "16:9",
 
1632
  ],
1633
  [
1634
  "highland.png",
1635
  "Realistic POV selfie-style video in a snowy, foggy field. Two shaggy Highland cows with long curved horns stand ahead. The camera is handheld and slightly shaky. The woman filming talks nervously and excitedly in a vlog tone: \"Oh my god guys… look how big those horns are… I’m kinda scared.\" The cow on the left walks toward the camera in a cute, bouncy, hopping way, curious and gentle. Snow crunches under its hooves, breath visible in the cold air. The horns look massive from the POV. As the cow gets very close, its wet nose with slight dripping fills part of the frame. She laughs nervously but reaches out and pets the cow. The cow makes deep, soft, interesting mooing and snorting sounds, calm and friendly. Ultra-realistic, natural lighting, immersive audio, documentary-style realism.",
1636
  "No LoRA",
1637
  "16:9",
 
1638
  ],
1639
  [
1640
  "wednesday.png",
1641
  "A cinematic dolly out of Wednesday Addams frozen mid-dance on a dark, blue-lit ballroom floor as students move indistinctly behind her, their footsteps and muffled music reduced to a distant, underwater thrum; the audio foregrounds her steady breathing and the faint rustle of fabric as she slowly raises one arm, never breaking eye contact with the camera, then after a deliberately long silence she speaks in a flat, dry, perfectly controlled voice, “I don’t dance… I vibe code,” each word crisp and unemotional, followed by an abrupt cutoff of her voice as the background sound swells slightly, reinforcing the deadpan humor, with precise lip sync, minimal facial movement, stark gothic lighting, and cinematic realism.",
1642
  "Zoom Out",
1643
  "16:9",
 
1644
  ],
1645
  [
1646
  "astronaut.png",
1647
  "An astronaut hatches from a fragile egg on the surface of the Moon, the shell cracking and peeling apart in gentle low-gravity motion. Fine lunar dust lifts and drifts outward with each movement, floating in slow arcs before settling back onto the ground. The astronaut pushes free in a deliberate, weightless motion, small fragments of the egg tumbling and spinning through the air. In the background, the deep darkness of space subtly shifts as stars glide with the camera's movement, emphasizing vast depth and scale. The camera performs a smooth, cinematic slow push-in, with natural parallax between the foreground dust, the astronaut, and the distant starfield. Ultra-realistic detail, physically accurate low-gravity motion, cinematic lighting, and a breath-taking, movie-like shot.",
1648
  "Static",
1649
  "1:1",
 
1650
  ],
1651
- # [
1652
- # "astronaut.png",
1653
- # "The video opens on object. A knife, held by a hand, is coming into frame and hovering over the object. The knife then begins cutting into the object to c4k3 cakeify them. As the knife slices the object open, the insides of the object are revealed to be cakes with chocolate layers. The knife cuts through and the contents of object are revealed.",
1654
- # "Cakify",
1655
- # ],
1656
- # [
1657
- # "astronaut.png",
1658
- # "The video showcases an item. The camera zooms out. Then infl4t3 inflates it, the item expanding into giant, inflated balloon against the landscape.",
1659
- # "Inflate",
1660
- # ],
1661
- # [
1662
- # "astronaut.png",
1663
- # "The video begins with an item. A hydraulic press positioned above slowly descends towards the item. Upon contact, the hydraulic press c5us4 crushes it, deforming and flattening the item, causing the item to collapse inward until the item is no longer recognizable.",
1664
- # "Hydraulic",
1665
- # ],
1666
 
1667
  ],
1668
  fn=generate_video_example,
1669
- inputs=[input_image, prompt_ui, camera_lora_ui, radioanimated_resolution],
1670
  outputs = [output_video],
1671
  label="I2V Examples",
1672
  cache_examples=True,
 
637
 
638
  class CameraDropdown(gr.HTML):
639
  """
640
+ Custom dropdown (More-style) with optional icons per item.
641
+ Outputs: selected option string, e.g. "16:9"
642
+
643
+ choices can be:
644
+ - ["16:9", "1:1", "9:16"] (text only)
645
+ - [{"label":"16:9","value":"16:9","icon":"…"}, ...] (icon+text)
646
+
647
+ icon can be emoji or inline SVG/HTML.
648
  """
649
+ def __init__(self, choices, value="None", title="Dropdown", **kwargs):
650
  if not choices:
651
  raise ValueError("CameraDropdown requires choices.")
652
 
653
+ # Normalize choices -> list of dicts: {label, value, icon(optional)}
654
+ norm = []
655
+ for c in choices:
656
+ if isinstance(c, dict):
657
+ label = str(c.get("label", c.get("value", "")))
658
+ val = str(c.get("value", label))
659
+ icon = c.get("icon", None) # emoji or svg/html
660
+ norm.append({"label": label, "value": val, "icon": icon})
661
+ else:
662
+ s = str(c)
663
+ norm.append({"label": s, "value": s, "icon": None})
664
+
665
  uid = uuid.uuid4().hex[:8]
 
666
 
667
+ def render_item(item):
668
+ icon_html = ""
669
+ if item["icon"]:
670
+ icon_html = f'<span class="cd-icn">{item["icon"]}</span>'
671
+ return (
672
+ f'<button type="button" class="cd-item" '
673
+ f'data-value="{item["value"]}">'
674
+ f'{icon_html}<span class="cd-label">{item["label"]}</span>'
675
+ f'</button>'
676
+ )
677
+
678
+ items_html = "\n".join(render_item(item) for item in norm)
679
 
680
  html_template = f"""
681
  <div class="cd-wrap" data-cd="{uid}">
682
+ <button type="button" class="cd-trigger" aria-haspopup="menu" aria-expanded="false">
683
+ <span class="cd-trigger-icon"></span>
684
+ <span class="cd-trigger-text"></span>
685
+ <span class="cd-caret">▾</span>
686
+ </button>
687
 
688
  <div class="cd-menu" role="menu" aria-hidden="true">
689
  <div class="cd-title">{title}</div>
 
694
  </div>
695
  """
696
 
697
+ # Pass a mapping value->label so the trigger can show label text
698
+ # (and still output value to Python)
699
+ value_to_label = {it["value"]: it["label"] for it in norm}
700
+ value_to_icon = {it["value"]: (it["icon"] or "") for it in norm}
701
+
702
  js_on_load = r"""
703
  (() => {
704
+ const wrap = element.querySelector(".cd-wrap");
705
+ const trigger = element.querySelector(".cd-trigger");
706
+ const triggerIcon = element.querySelector(".cd-trigger-icon");
707
+ const triggerText = element.querySelector(".cd-trigger-text");
708
+ const menu = element.querySelector(".cd-menu");
709
+ const items = Array.from(element.querySelectorAll(".cd-item"));
710
+ if (!wrap || !trigger || !menu || !items.length) return;
711
+
712
+ const valueToLabel = __VALUE_TO_LABEL__;
713
+ const valueToIcon = __VALUE_TO_ICON__;
714
+
715
+ const safeLabel = (v) => (valueToLabel && valueToLabel[v]) ? valueToLabel[v] : (v ?? "None");
716
+ const safeIcon = (v) => (valueToIcon && valueToIcon[v]) ? valueToIcon[v] : "";
717
 
 
718
 
719
+ function closeMenu() {
720
  menu.classList.remove("open");
721
  trigger.setAttribute("aria-expanded", "false");
722
  menu.setAttribute("aria-hidden", "true");
723
+ }
724
 
725
+ function openMenu() {
726
  menu.classList.add("open");
727
  trigger.setAttribute("aria-expanded", "true");
728
  menu.setAttribute("aria-hidden", "false");
729
+ }
730
 
731
+ function setValue(val, shouldTrigger = false) {
732
+ const v = (val ?? "None");
733
+ props.value = v;
734
+
735
+ // Trigger shows LABEL only (icons stay in menu)
736
+ triggerText.textContent = safeLabel(v);
737
+ if (triggerIcon) {
738
+ triggerIcon.innerHTML = safeIcon(v);
739
+ triggerIcon.style.display = safeIcon(v) ? "inline-flex" : "none";
740
+ }
 
 
741
 
742
+
743
+ items.forEach(btn => {
744
+ btn.dataset.selected = (btn.dataset.value === v) ? "true" : "false";
745
+ });
746
+
747
+ if (shouldTrigger) trigger("change", props.value);
748
+ }
749
+
750
+ trigger.addEventListener("pointerdown", (e) => {
751
+ e.preventDefault();
752
  e.stopPropagation();
753
  if (menu.classList.contains("open")) closeMenu();
754
  else openMenu();
755
+ });
756
 
757
+ document.addEventListener("pointerdown", (e) => {
 
758
  if (!wrap.contains(e.target)) closeMenu();
759
+ }, true);
760
 
761
+ document.addEventListener("keydown", (e) => {
 
762
  if (e.key === "Escape") closeMenu();
763
+ });
764
 
765
+ wrap.addEventListener("focusout", (e) => {
 
 
766
  if (!wrap.contains(e.relatedTarget)) closeMenu();
767
+ });
768
 
769
+ items.forEach((btn) => {
 
770
  btn.addEventListener("pointerdown", (e) => {
771
+ e.preventDefault();
772
+ e.stopPropagation();
773
+ closeMenu();
774
+ setValue(btn.dataset.value, true);
 
 
775
  });
776
+ });
777
 
778
+ // init
779
+ setValue((props.value ?? "None"), false);
780
 
781
+ // sync from Python
782
+ let last = props.value;
783
+ const syncFromProps = () => {
784
  if (props.value !== last) {
785
+ last = props.value;
786
+ setValue(last, false);
787
  }
788
  requestAnimationFrame(syncFromProps);
789
+ };
790
+ requestAnimationFrame(syncFromProps);
791
  })();
 
792
  """
793
 
794
+ # Inject mapping into JS safely
795
+ import json
796
+ js_on_load = js_on_load.replace("__VALUE_TO_LABEL__", json.dumps(value_to_label))
797
+ js_on_load = js_on_load.replace("__VALUE_TO_ICON__", json.dumps(value_to_icon))
798
+
799
  super().__init__(
800
  value=value,
801
  html_template=html_template,
 
803
  **kwargs
804
  )
805
 
806
+ def generate_video_example(input_image, prompt, camera_lora, resolution, audio_path = None, progress=gr.Progress(track_tqdm=True)):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
807
 
808
  w, h = apply_resolution(resolution)
809
 
 
1123
  }
1124
  """
1125
 
1126
+ css += """
1127
+ .cd-trigger-icon{
1128
+ color: rgba(255,255,255,0.9);
1129
+ display: inline-flex;
1130
+ align-items: center;
1131
+ justify-content: center;
1132
+ width: 18px;
1133
+ height: 18px;
1134
+ }
1135
+ .cd-trigger-icon svg {
1136
+ width: 18px;
1137
+ height: 18px;
1138
+ display: block;
1139
+ }
1140
+ """
1141
+
1142
+
1143
  css += """
1144
  /* ---- radioanimated ---- */
1145
  .ra-wrap{
 
1187
  }
1188
  """
1189
 
1190
+ css += """
1191
+ .cd-icn svg{
1192
+ width: 18px;
1193
+ height: 18px;
1194
+ display: block;
1195
+ }
1196
+ .cd-icn svg *{
1197
+ stroke: rgba(255,255,255,0.9);
1198
+ }
1199
+ """
1200
+
1201
+
1202
  css += """
1203
  /* --- prompt box --- */
1204
  .ds-prompt{
 
1400
 
1401
  """
1402
 
1403
+ css += """
1404
+ /* icons in dropdown items */
1405
+ .cd-item{
1406
+ display: flex;
1407
+ align-items: center;
1408
+ gap: 10px;
1409
+ }
1410
+ .cd-icn{
1411
+ display: inline-flex;
1412
+ align-items: center;
1413
+ justify-content: center;
1414
+ width: 18px;
1415
+ height: 18px;
1416
+ flex: 0 0 18px;
1417
+ }
1418
+ .cd-label{
1419
+ flex: 1;
1420
+ }
1421
+ """
1422
+
1423
 
1424
 
1425
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
 
1514
  visible=False
1515
  )
1516
 
1517
+ ICON_16_9 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
1518
+ <rect x="3" y="7" width="18" height="10" rx="2" stroke="currentColor" stroke-width="2"/>
1519
+ </svg>"""
1520
+
1521
+ ICON_1_1 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
1522
+ <rect x="6" y="6" width="12" height="12" rx="2" stroke="currentColor" stroke-width="2"/>
1523
+ </svg>"""
1524
+
1525
+ ICON_9_16 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
1526
+ <rect x="7" y="3" width="10" height="18" rx="2" stroke="currentColor" stroke-width="2"/>
1527
+ </svg>"""
1528
+
1529
+
1530
  radioanimated_resolution = CameraDropdown(
1531
+ choices=[
1532
+ {"label": "16:9", "value": "16:9", "icon": ICON_16_9},
1533
+ {"label": "1:1", "value": "1:1", "icon": ICON_1_1},
1534
+ {"label": "9:16", "value": "9:16", "icon": ICON_9_16},
1535
+ ],
1536
  value="16:9",
1537
  title="Resolution",
1538
  elem_id="radioanimated_resolution"
1539
  )
1540
+
1541
 
1542
  width = gr.Number(label="Width", value=DEFAULT_1_STAGE_WIDTH, precision=0, visible=False)
1543
  height = gr.Number(label="Height", value=DEFAULT_1_STAGE_HEIGHT, precision=0, visible=False)
 
1559
 
1560
  generate_btn = gr.Button("🤩 Generate Video", variant="primary", elem_classes="button-gradient")
1561
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1562
  camera_lora_ui.change(
1563
  fn=lambda x: x,
1564
  inputs=camera_lora_ui,
 
1603
  outputs=[output_video]
1604
  )
1605
 
1606
+ # Add example
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1607
  gr.Examples(
1608
  examples=[
 
1609
  [
1610
  "supergirl-2.png",
1611
  "A fuzzy puppet superhero character resembling a female puppet with blonde hair and a blue superhero suit sleeping in bed and just waking up, she gradually gets up, rubbing her eyes and looking at her dog that just popped on the bed. the scene feels chaotic, comedic, and emotional with expressive puppet reactions, cinematic lighting, smooth camera motion, shallow depth of field, and high-quality puppet-style animation",
 
1613
  "16:9",
1614
  "supergirl.m4a"
1615
  ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1616
  [
1617
  "supergirl.png",
1618
  "A fuzzy puppet superhero character resembling a female puppet with blonde hair and a blue superhero suit stands inside an icy cave made of frozen walls and icicles, she looks panicked and frantic, rapidly turning her head left and right and scanning the cave while waving her arms and shouting angrily and desperately, mouthing the words “where the hell is my dog,” her movements exaggerated and puppet-like with high energy and urgency, suddenly a second puppet dog bursts into frame from the side, jumping up excitedly and tackling her affectionately while licking her face repeatedly, she freezes in surprise and then breaks into relief and laughter as the dog continues licking her, the scene feels chaotic, comedic, and emotional with expressive puppet reactions, cinematic lighting, smooth camera motion, shallow depth of field, and high-quality puppet-style animation",
1619
+ "No LoRA",
1620
  "16:9",
1621
+ None,
1622
  ],
1623
  [
1624
  "highland.png",
1625
  "Realistic POV selfie-style video in a snowy, foggy field. Two shaggy Highland cows with long curved horns stand ahead. The camera is handheld and slightly shaky. The woman filming talks nervously and excitedly in a vlog tone: \"Oh my god guys… look how big those horns are… I’m kinda scared.\" The cow on the left walks toward the camera in a cute, bouncy, hopping way, curious and gentle. Snow crunches under its hooves, breath visible in the cold air. The horns look massive from the POV. As the cow gets very close, its wet nose with slight dripping fills part of the frame. She laughs nervously but reaches out and pets the cow. The cow makes deep, soft, interesting mooing and snorting sounds, calm and friendly. Ultra-realistic, natural lighting, immersive audio, documentary-style realism.",
1626
  "No LoRA",
1627
  "16:9",
1628
+ None,
1629
  ],
1630
  [
1631
  "wednesday.png",
1632
  "A cinematic dolly out of Wednesday Addams frozen mid-dance on a dark, blue-lit ballroom floor as students move indistinctly behind her, their footsteps and muffled music reduced to a distant, underwater thrum; the audio foregrounds her steady breathing and the faint rustle of fabric as she slowly raises one arm, never breaking eye contact with the camera, then after a deliberately long silence she speaks in a flat, dry, perfectly controlled voice, “I don’t dance… I vibe code,” each word crisp and unemotional, followed by an abrupt cutoff of her voice as the background sound swells slightly, reinforcing the deadpan humor, with precise lip sync, minimal facial movement, stark gothic lighting, and cinematic realism.",
1633
  "Zoom Out",
1634
  "16:9",
1635
+ None,
1636
  ],
1637
  [
1638
  "astronaut.png",
1639
  "An astronaut hatches from a fragile egg on the surface of the Moon, the shell cracking and peeling apart in gentle low-gravity motion. Fine lunar dust lifts and drifts outward with each movement, floating in slow arcs before settling back onto the ground. The astronaut pushes free in a deliberate, weightless motion, small fragments of the egg tumbling and spinning through the air. In the background, the deep darkness of space subtly shifts as stars glide with the camera's movement, emphasizing vast depth and scale. The camera performs a smooth, cinematic slow push-in, with natural parallax between the foreground dust, the astronaut, and the distant starfield. Ultra-realistic detail, physically accurate low-gravity motion, cinematic lighting, and a breath-taking, movie-like shot.",
1640
  "Static",
1641
  "1:1",
1642
+ None,
1643
  ],
1644
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1645
 
1646
  ],
1647
  fn=generate_video_example,
1648
+ inputs=[input_image, prompt_ui, camera_lora_ui, radioanimated_resolution, audio_input],
1649
  outputs = [output_video],
1650
  label="I2V Examples",
1651
  cache_examples=True,