space: interactive replay demo — fast-forward 22s through real generation stages, with 6 real SF walk keyframes
Browse files- app.py +171 -16
- showcase/frame_000002.png +3 -0
- showcase/frame_000009.png +3 -0
- showcase/frame_000013.png +3 -0
- showcase/frame_000018.png +3 -0
- showcase/frame_000023.png +3 -0
- showcase/frame_000028.png +3 -0
app.py
CHANGED
|
@@ -245,6 +245,134 @@ def refresh_gallery():
|
|
| 245 |
return render_demo_grid(fetch_demos())
|
| 246 |
|
| 247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
CUSTOM_CSS = r"""
|
| 249 |
/* Force dark theme regardless of system / browser preference.
|
| 250 |
Overrides Gradio's neutral scale (used as bg in light mode) to dark values
|
|
@@ -1300,23 +1428,50 @@ def build_ui():
|
|
| 1300 |
|
| 1301 |
with gr.Tab("Live demo"):
|
| 1302 |
gr.Markdown(
|
| 1303 |
-
"##
|
| 1304 |
-
"
|
| 1305 |
-
"
|
| 1306 |
-
"
|
| 1307 |
-
"
|
| 1308 |
-
"
|
| 1309 |
-
"
|
| 1310 |
-
"
|
| 1311 |
-
"
|
| 1312 |
-
"**vs Sora & Runway** tab for the full breakdown."
|
| 1313 |
)
|
| 1314 |
-
gr.
|
| 1315 |
-
|
| 1316 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1317 |
)
|
| 1318 |
-
demo_refresh = gr.Button("Refresh archive", size="sm")
|
| 1319 |
-
demo_refresh.click(refresh_gallery, outputs=[demo_gallery])
|
| 1320 |
|
| 1321 |
with gr.Tab("vs Sora & Runway"):
|
| 1322 |
gr.Markdown(
|
|
@@ -1552,5 +1707,5 @@ if __name__ == "__main__":
|
|
| 1552 |
demo = build_ui()
|
| 1553 |
demo.queue(default_concurrency_limit=1, max_size=8).launch(
|
| 1554 |
server_name="0.0.0.0", server_port=7860, share=False,
|
| 1555 |
-
allowed_paths=[str(DEMO_CACHE)],
|
| 1556 |
)
|
|
|
|
| 245 |
return render_demo_grid(fetch_demos())
|
| 246 |
|
| 247 |
|
| 248 |
+
# Fast-forward replay of an actual MI300X generation run. The frames + final mp4
|
| 249 |
+
# in showcase/ are real artifacts from this prompt. Timings on the left are the
|
| 250 |
+
# actual wall-clock from incidents.md; the replay compresses ~81 min to ~22 s.
|
| 251 |
+
SF_PROMPT = (
|
| 252 |
+
"30-second cinematic reel: a young woman walks alone through San Francisco at "
|
| 253 |
+
"golden hour — down a steep Pacific Heights street with bay views, past painted "
|
| 254 |
+
"Victorian houses, fog rolling in over the Pacific, ending at a quiet overlook "
|
| 255 |
+
"of the Golden Gate Bridge as the light shifts to blue hour."
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
REPLAY_FRAMES = [
|
| 259 |
+
"frame_000002.png",
|
| 260 |
+
"frame_000009.png",
|
| 261 |
+
"frame_000013.png",
|
| 262 |
+
"frame_000018.png",
|
| 263 |
+
"frame_000023.png",
|
| 264 |
+
"frame_000028.png",
|
| 265 |
+
]
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
def _frame_url(name):
|
| 269 |
+
return f"/gradio_api/file={SHOWCASE_DIR / name}"
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
def replay_generation():
|
| 273 |
+
"""Yield (status_md, gallery_html, video_update) progressively, simulating
|
| 274 |
+
the real pipeline at ~80x speed so a visitor can see every stage in 22 s."""
|
| 275 |
+
log_lines = []
|
| 276 |
+
gallery = ""
|
| 277 |
+
hidden = gr.update(visible=False)
|
| 278 |
+
|
| 279 |
+
def emit(line):
|
| 280 |
+
log_lines.append(line)
|
| 281 |
+
return "\n\n".join(log_lines)
|
| 282 |
+
|
| 283 |
+
yield emit(
|
| 284 |
+
"**`[00:00]`** 🎬 Director Agent loading — `Qwen3.5-35B-A3B` via vLLM + AITER MoE…"
|
| 285 |
+
), gallery, hidden
|
| 286 |
+
time.sleep(0.7)
|
| 287 |
+
|
| 288 |
+
yield emit(
|
| 289 |
+
"**`[00:02]`** ✏️ Planning 6 shots, character bibles, music brief, narration language…"
|
| 290 |
+
), gallery, hidden
|
| 291 |
+
time.sleep(1.2)
|
| 292 |
+
|
| 293 |
+
plan_block = (
|
| 294 |
+
"```json\n"
|
| 295 |
+
'{\n'
|
| 296 |
+
' "characters": {\n'
|
| 297 |
+
' "A": "young woman, 27, navy peacoat, soft scarf, walking calmly"\n'
|
| 298 |
+
' },\n'
|
| 299 |
+
' "story_logline": "Pacific Heights walk through fog to Golden Gate overlook",\n'
|
| 300 |
+
' "music_style": "intimate ambient piano + soft synth pad, 75 BPM",\n'
|
| 301 |
+
' "vo_lang": "a" // Director picked American English from setting\n'
|
| 302 |
+
'}\n'
|
| 303 |
+
"```"
|
| 304 |
+
)
|
| 305 |
+
yield emit(plan_block), gallery, hidden
|
| 306 |
+
time.sleep(0.6)
|
| 307 |
+
|
| 308 |
+
yield emit(
|
| 309 |
+
"**`[00:04]`** 🎨 FLUX.2 [klein] — painting character master portraits "
|
| 310 |
+
"*(reference editing, no LoRA training)*…"
|
| 311 |
+
), gallery, hidden
|
| 312 |
+
time.sleep(0.9)
|
| 313 |
+
|
| 314 |
+
yield emit(
|
| 315 |
+
"**`[00:06]`** 🎞️ FLUX.2 — 6 per-shot keyframes, character-consistent across shots…"
|
| 316 |
+
), gallery, hidden
|
| 317 |
+
time.sleep(0.5)
|
| 318 |
+
|
| 319 |
+
for idx, frame in enumerate(REPLAY_FRAMES):
|
| 320 |
+
gallery += (
|
| 321 |
+
f'<img src="{_frame_url(frame)}" '
|
| 322 |
+
f'style="width:30%;margin:1%;border-radius:8px;'
|
| 323 |
+
f'border:1px solid rgba(167,139,250,0.32);" '
|
| 324 |
+
f'alt="keyframe shot {idx}">'
|
| 325 |
+
)
|
| 326 |
+
yield log_lines and "\n\n".join(log_lines) or "", gallery, hidden
|
| 327 |
+
time.sleep(0.35)
|
| 328 |
+
|
| 329 |
+
yield emit(
|
| 330 |
+
"**`[00:09]`** 🎥 Wan2.2-I2V-A14B — animating each shot "
|
| 331 |
+
"*(FBCache lossless 2× + torch.compile 1.2× = ~10 min per clip on MI300X)*…"
|
| 332 |
+
), gallery, hidden
|
| 333 |
+
time.sleep(0.4)
|
| 334 |
+
|
| 335 |
+
progress_line_idx = len(log_lines)
|
| 336 |
+
log_lines.append("")
|
| 337 |
+
for i in range(1, 7):
|
| 338 |
+
bars = "▰" * i + "▱" * (6 - i)
|
| 339 |
+
log_lines[progress_line_idx] = f" `shot {i}/6` {bars}"
|
| 340 |
+
yield "\n\n".join(log_lines), gallery, hidden
|
| 341 |
+
time.sleep(0.28)
|
| 342 |
+
|
| 343 |
+
yield emit(
|
| 344 |
+
"**`[00:15]`** 🔍 Vision Critic — Qwen3.5 reloaded, scoring 4 frames per clip "
|
| 345 |
+
"on a 10-label failure taxonomy…"
|
| 346 |
+
), gallery, hidden
|
| 347 |
+
time.sleep(0.8)
|
| 348 |
+
yield emit(
|
| 349 |
+
" `shot 0` ✅ overall **9/10** "
|
| 350 |
+
"*(character_match=10, scene=9, composition=9, artifact_free=9)* — no retry\n\n"
|
| 351 |
+
" `shots 1–5` ✅ all pass first attempt"
|
| 352 |
+
), gallery, hidden
|
| 353 |
+
time.sleep(0.7)
|
| 354 |
+
|
| 355 |
+
yield emit(
|
| 356 |
+
"**`[00:17]`** 🎵 ACE-Step v1 — generating 30 s instrumental from Director's brief…"
|
| 357 |
+
), gallery, hidden
|
| 358 |
+
time.sleep(0.5)
|
| 359 |
+
|
| 360 |
+
yield emit(
|
| 361 |
+
"**`[00:19]`** 🗣️ Kokoro-82M — narrating per-shot voice-over, language picked by Director *(en-US)*…"
|
| 362 |
+
), gallery, hidden
|
| 363 |
+
time.sleep(0.4)
|
| 364 |
+
|
| 365 |
+
yield emit(
|
| 366 |
+
"**`[00:21]`** 🎚️ ffmpeg — mixing music bed + per-shot VO via `adelay`, concat, loudnorm -18 LUFS…"
|
| 367 |
+
), gallery, hidden
|
| 368 |
+
time.sleep(0.6)
|
| 369 |
+
|
| 370 |
+
yield emit(
|
| 371 |
+
"**`[00:22]`** ✅ **Final reel rendered.** Real wall-time on MI300X: **~81 minutes**.\n\n"
|
| 372 |
+
"> *This replay compressed 81 minutes into 22 seconds. The mp4 below is the actual output of the run shown above.*"
|
| 373 |
+
), gallery, gr.update(value=str(SHOWCASE_DIR / "sf_walk.mp4"), visible=True)
|
| 374 |
+
|
| 375 |
+
|
| 376 |
CUSTOM_CSS = r"""
|
| 377 |
/* Force dark theme regardless of system / browser preference.
|
| 378 |
Overrides Gradio's neutral scale (used as bg in light mode) to dark values
|
|
|
|
| 1428 |
|
| 1429 |
with gr.Tab("Live demo"):
|
| 1430 |
gr.Markdown(
|
| 1431 |
+
"## See it generate — fast-forward replay\n\n"
|
| 1432 |
+
"This is a real MI300X generation run from the hackathon, "
|
| 1433 |
+
"compressed from **~81 minutes wall-time to 22 seconds**. Every "
|
| 1434 |
+
"image and the final mp4 below is the actual artifact the pipeline "
|
| 1435 |
+
"produced from the prompt on the left. Hit **▶ Replay generation** "
|
| 1436 |
+
"to watch every stage scroll past — Director plan, FLUX.2 keyframes, "
|
| 1437 |
+
"Wan2.2 animation, Vision Critic verdict, music, voice-over, mix.\n\n"
|
| 1438 |
+
"> *(Live on-demand generation is paused — hackathon ended. This is "
|
| 1439 |
+
"a deterministic replay of one production run.)*"
|
|
|
|
| 1440 |
)
|
| 1441 |
+
with gr.Row():
|
| 1442 |
+
with gr.Column(scale=1):
|
| 1443 |
+
gr.Markdown("### Prompt")
|
| 1444 |
+
gr.Textbox(
|
| 1445 |
+
value=SF_PROMPT,
|
| 1446 |
+
lines=6,
|
| 1447 |
+
interactive=False,
|
| 1448 |
+
label="One English sentence in",
|
| 1449 |
+
show_copy_button=True,
|
| 1450 |
+
)
|
| 1451 |
+
replay_btn = gr.Button(
|
| 1452 |
+
"▶ Replay generation",
|
| 1453 |
+
variant="primary",
|
| 1454 |
+
size="lg",
|
| 1455 |
+
)
|
| 1456 |
+
gr.Markdown("### Pipeline log")
|
| 1457 |
+
replay_log = gr.Markdown(
|
| 1458 |
+
"_Click ▶ Replay generation to start. Each stage updates "
|
| 1459 |
+
"as it would on the actual MI300X, just sped up ~220×._"
|
| 1460 |
+
)
|
| 1461 |
+
with gr.Column(scale=2):
|
| 1462 |
+
gr.Markdown("### Artifacts as they appear")
|
| 1463 |
+
replay_gallery = gr.HTML("")
|
| 1464 |
+
replay_video = gr.Video(
|
| 1465 |
+
label="Final 30 s reel",
|
| 1466 |
+
visible=False,
|
| 1467 |
+
autoplay=True,
|
| 1468 |
+
loop=True,
|
| 1469 |
+
interactive=False,
|
| 1470 |
+
)
|
| 1471 |
+
replay_btn.click(
|
| 1472 |
+
replay_generation,
|
| 1473 |
+
outputs=[replay_log, replay_gallery, replay_video],
|
| 1474 |
)
|
|
|
|
|
|
|
| 1475 |
|
| 1476 |
with gr.Tab("vs Sora & Runway"):
|
| 1477 |
gr.Markdown(
|
|
|
|
| 1707 |
demo = build_ui()
|
| 1708 |
demo.queue(default_concurrency_limit=1, max_size=8).launch(
|
| 1709 |
server_name="0.0.0.0", server_port=7860, share=False,
|
| 1710 |
+
allowed_paths=[str(DEMO_CACHE), str(SHOWCASE_DIR)],
|
| 1711 |
)
|
showcase/frame_000002.png
ADDED
|
Git LFS Details
|
showcase/frame_000009.png
ADDED
|
Git LFS Details
|
showcase/frame_000013.png
ADDED
|
Git LFS Details
|
showcase/frame_000018.png
ADDED
|
Git LFS Details
|
showcase/frame_000023.png
ADDED
|
Git LFS Details
|
showcase/frame_000028.png
ADDED
|
Git LFS Details
|