Abetharan Claude Opus 4.6 (1M context) commited on
Commit
08e4c2c
·
1 Parent(s): 9a12219

Pre-render frames into MP4 video for smooth playback

Browse files

Replace frame-by-frame generator with pre-rendered video using imageio.
Swap gr.Image for gr.Video with autoplay and loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +19 -14
  2. requirements.txt +1 -0
app.py CHANGED
@@ -6,10 +6,12 @@ Loads precomputed rollout cache and auto-plays animation on sample selection.
6
  import io
7
  import os
8
  import pickle
 
9
  import time
10
  from pathlib import Path
11
 
12
  import gradio as gr
 
13
  import matplotlib
14
  matplotlib.use("Agg")
15
  import matplotlib.pyplot as plt
@@ -185,7 +187,7 @@ def _format_params_html(params):
185
  # Callbacks — auto-play animation as a generator
186
  # ---------------------------------------------------------------------------
187
  def on_random_sample(channel_name):
188
- """Pick a random trajectory and auto-play the full animation."""
189
  traj_idx = int(np.random.randint(0, NUM_TRAJS))
190
  entry = CACHE[traj_idx]
191
  num_steps = entry["num_steps"]
@@ -199,19 +201,22 @@ def on_random_sample(channel_name):
199
  f"&nbsp;|&nbsp; Steps: <b>{num_steps}</b></div>"
200
  )
201
 
202
- # Yield each frame for auto-play
 
203
  for step in range(num_steps):
204
- fig = render_comparison_frame(traj_idx, step, channel_name)
205
- time_str = ""
206
- if entry["time_values"] is not None and step < len(entry["time_values"]):
207
- time_str = f"t = {entry['time_values'][step]:.3e} &nbsp;|&nbsp; "
208
- step_info = (
209
- f"<div class='metrics-bar'>"
210
- f"{time_str}"
211
- f"Step <b>{step+1}/{num_steps}</b></div>"
212
- )
213
- yield fig, params_html, step_info
214
- time.sleep(0.1)
 
 
215
 
216
 
217
  # ---------------------------------------------------------------------------
@@ -343,7 +348,7 @@ def main():
343
  metrics_bar = gr.HTML(
344
  value="<div class='metrics-bar'>Click <b>Random Sample</b> to begin</div>"
345
  )
346
- plot_output = gr.Image(label="Comparison")
347
 
348
  random_btn.click(
349
  fn=on_random_sample,
 
6
  import io
7
  import os
8
  import pickle
9
+ import tempfile
10
  import time
11
  from pathlib import Path
12
 
13
  import gradio as gr
14
+ import imageio
15
  import matplotlib
16
  matplotlib.use("Agg")
17
  import matplotlib.pyplot as plt
 
187
  # Callbacks — auto-play animation as a generator
188
  # ---------------------------------------------------------------------------
189
  def on_random_sample(channel_name):
190
+ """Pick a random trajectory and pre-render a smooth video."""
191
  traj_idx = int(np.random.randint(0, NUM_TRAJS))
192
  entry = CACHE[traj_idx]
193
  num_steps = entry["num_steps"]
 
201
  f"&nbsp;|&nbsp; Steps: <b>{num_steps}</b></div>"
202
  )
203
 
204
+ # Pre-render all frames
205
+ frames = []
206
  for step in range(num_steps):
207
+ img = render_comparison_frame(traj_idx, step, channel_name)
208
+ frames.append(np.array(img))
209
+
210
+ # Write frames to an MP4 video
211
+ video_path = tempfile.mktemp(suffix=".mp4")
212
+ fps = 10
213
+ writer = imageio.get_writer(video_path, fps=fps, codec="libx264",
214
+ output_params=["-pix_fmt", "yuv420p"])
215
+ for frame in frames:
216
+ writer.append_data(frame)
217
+ writer.close()
218
+
219
+ return video_path, params_html, info
220
 
221
 
222
  # ---------------------------------------------------------------------------
 
348
  metrics_bar = gr.HTML(
349
  value="<div class='metrics-bar'>Click <b>Random Sample</b> to begin</div>"
350
  )
351
+ plot_output = gr.Video(label="Comparison", autoplay=True, loop=True)
352
 
353
  random_btn.click(
354
  fn=on_random_sample,
requirements.txt CHANGED
@@ -2,3 +2,4 @@ numpy
2
  matplotlib
3
  Pillow
4
  huggingface_hub
 
 
2
  matplotlib
3
  Pillow
4
  huggingface_hub
5
+ imageio[ffmpeg]