Hwihwa_Lab commited on
Commit
e780fe4
ยท
1 Parent(s): 566f223

feat: upgrade replay.mp4 to 1:1 square (720x720) close-up viewport for HF video preview widget

Browse files
Files changed (2) hide show
  1. record_replay_mp4.py +60 -36
  2. replay.mp4 +2 -2
record_replay_mp4.py CHANGED
@@ -1,12 +1,12 @@
1
  # -*- coding: utf-8 -*-
2
  """
3
- HWIHWA LAB // Ultra-High-Definition Canvas-Focused `replay.mp4` Generator
4
- Directly captures the simulation stage canvas (.canvas-viewport-area) with:
5
- 1) 100% Focused Stage: No unnecessary control buttons or settings clutter
6
- 2) Huge, clear Cart & Pole catching dynamics
7
- 3) Crisp Mouse Shock Impulse Laser & Shock Banner
8
- 4) Real-time Phase Portrait Attractor Convergence Radar
9
- 5) High-bitrate H.264 (CRF 16) for razor-sharp visual clarity
10
  """
11
 
12
  import time
@@ -17,65 +17,89 @@ from PIL import Image
17
  import imageio
18
  from playwright.sync_api import sync_playwright
19
 
20
- def generate_crisp_canvas_replay():
21
  current_dir = Path(__file__).resolve().parent
22
  html_url = f"file:///{current_dir.as_posix()}/index.html"
23
  output_mp4 = current_dir / "replay.mp4"
24
 
25
  raw_frames = []
26
 
27
- print("๐Ÿš€ Launching Headless Chromium to record ULTRA-CRISP Canvas Focus...")
28
  with sync_playwright() as p:
29
  browser = p.chromium.launch(headless=True)
30
- # Higher resolution 1440x900 viewport for retina-grade crisp canvas rendering
31
- context = browser.new_context(viewport={"width": 1440, "height": 900}, device_scale_factor=1)
32
  page = context.new_page()
33
 
34
  page.goto(html_url)
35
- page.wait_for_timeout(1000) # Wait for weights, physics & chart initialization
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- # Focus directly on the canvas viewport area (Stage only!)
38
  stage = page.locator(".canvas-viewport-area")
39
  box = stage.bounding_box()
40
  if not box:
41
- print("[!] Could not find .canvas-viewport-area, falling back to #simCanvas")
42
  stage = page.locator("#simCanvas")
43
  box = stage.bounding_box()
44
 
45
- cx = box["x"] + box["width"] / 2
46
- cy = box["y"] + box["height"] / 2
47
-
48
  print(f" ๐ŸŽฏ Stage Bounding Box: Width={box['width']}, Height={box['height']}")
49
 
50
- total_frames = 100 # ~4 seconds @ 25 FPS
51
  for i in range(total_frames):
52
- # Trigger realistic mouse drag disturbance impulse at frame 22-28
53
- if i == 20:
54
- page.mouse.move(cx - 30, cy + 30)
 
 
 
 
 
 
 
 
 
55
  page.mouse.down()
56
- elif i == 24:
57
- page.mouse.move(cx + 180, cy - 45)
58
- elif i == 28:
59
  page.mouse.up()
60
 
61
- # Capture direct stage element screenshot for 100% canvas focus
62
  screenshot_bytes = stage.screenshot(type="png")
63
  img = Image.open(io.BytesIO(screenshot_bytes))
64
 
65
- # Ensure even dimensions for H.264 macroblock compatibility (e.g., 1200x520)
66
- target_w = (img.width // 2) * 2
67
- target_h = (img.height // 2) * 2
68
- if img.width != target_w or img.height != target_h:
69
- img = img.resize((target_w, target_h), Image.Resampling.LANCZOS)
70
 
71
  raw_frames.append(np.array(img.convert("RGB")))
72
- time.sleep(0.038)
73
 
74
  browser.close()
75
 
76
- print(f"๐ŸŽฌ Encoding {len(raw_frames)} ultra-crisp frames to H.264 replay.mp4 (High Quality CRF)...")
77
-
78
- # High-bitrate encoding with ffmpeg parameters
79
  writer = imageio.get_writer(
80
  str(output_mp4),
81
  fps=25,
@@ -88,8 +112,8 @@ def generate_crisp_canvas_replay():
88
  writer.close()
89
 
90
  size_kb = round(output_mp4.stat().st_size / 1024, 1)
91
- print(f"[โœ“] SUCCESS: Ultra-Crisp Canvas Replay ready at: {output_mp4} ({size_kb} KB)")
92
  return output_mp4
93
 
94
  if __name__ == "__main__":
95
- generate_crisp_canvas_replay()
 
1
  # -*- coding: utf-8 -*-
2
  """
3
+ HWIHWA LAB // Ultra-High-Definition 1:1 Square (720x720) Replay Video Generator
4
+ Optimized specifically for Hugging Face Model Hub's Video Preview Sidebar Widget.
5
+ - 1:1 Square Aspect Ratio (720x720)
6
+ - Huge, bold Cart & Pole dynamics centered in the viewport
7
+ - Big shock impulse laser & particle physics
8
+ - Clean HUD overlay (Active force, score, shock banner)
9
+ - Ultra-sharp H.264 (CRF 17, 25 FPS)
10
  """
11
 
12
  import time
 
17
  import imageio
18
  from playwright.sync_api import sync_playwright
19
 
20
+ def generate_square_canvas_replay():
21
  current_dir = Path(__file__).resolve().parent
22
  html_url = f"file:///{current_dir.as_posix()}/index.html"
23
  output_mp4 = current_dir / "replay.mp4"
24
 
25
  raw_frames = []
26
 
27
+ print("๐Ÿš€ Launching Headless Chromium to record 1:1 SQUARE (720x720) CartPole Dynamics...")
28
  with sync_playwright() as p:
29
  browser = p.chromium.launch(headless=True)
30
+ # 720x720 Square Viewport with device_scale_factor=1
31
+ context = browser.new_context(viewport={"width": 720, "height": 720}, device_scale_factor=1)
32
  page = context.new_page()
33
 
34
  page.goto(html_url)
35
+ page.wait_for_timeout(1000) # Wait for weights & chart initialization
36
+
37
+ # Maximize Stage to 100% of 720x720 viewport
38
+ page.evaluate("""() => {
39
+ const header = document.querySelector('.header-bar');
40
+ if (header) header.style.display = 'none';
41
+ const bento = document.querySelector('.bento-deck-golden');
42
+ if (bento) bento.style.display = 'none';
43
+ const labMain = document.querySelector('.lab-main');
44
+ if (labMain) {
45
+ labMain.style.padding = '0';
46
+ labMain.style.height = '100vh';
47
+ }
48
+ const stageSec = document.querySelector('.stage-section');
49
+ if (stageSec) stageSec.style.height = '100vh';
50
+ const area = document.querySelector('.canvas-viewport-area');
51
+ if (area) {
52
+ area.style.height = '100vh';
53
+ area.style.borderRadius = '0';
54
+ area.style.border = 'none';
55
+ }
56
+ window.dispatchEvent(new Event('resize'));
57
+ }""")
58
+ page.wait_for_timeout(300)
59
 
 
60
  stage = page.locator(".canvas-viewport-area")
61
  box = stage.bounding_box()
62
  if not box:
 
63
  stage = page.locator("#simCanvas")
64
  box = stage.bounding_box()
65
 
66
+ cx = 360
67
+ cy = 360
 
68
  print(f" ๐ŸŽฏ Stage Bounding Box: Width={box['width']}, Height={box['height']}")
69
 
70
+ total_frames = 110 # ~4.4 seconds @ 25 FPS
71
  for i in range(total_frames):
72
+ # Apply dynamic mouse disturbance impulse
73
+ if i == 25:
74
+ page.mouse.move(cx - 20, cy + 50)
75
+ page.mouse.down()
76
+ elif i == 30:
77
+ page.mouse.move(cx + 140, cy - 40)
78
+ elif i == 35:
79
+ page.mouse.up()
80
+
81
+ # Optional second gentle tap at frame 70
82
+ if i == 70:
83
+ page.mouse.move(cx + 20, cy + 40)
84
  page.mouse.down()
85
+ elif i == 74:
86
+ page.mouse.move(cx - 80, cy - 30)
87
+ elif i == 78:
88
  page.mouse.up()
89
 
 
90
  screenshot_bytes = stage.screenshot(type="png")
91
  img = Image.open(io.BytesIO(screenshot_bytes))
92
 
93
+ # Resize precisely to 720x720 if slight pixel sub-pixel rounding occurs
94
+ if img.width != 720 or img.height != 720:
95
+ img = img.resize((720, 720), Image.Resampling.LANCZOS)
 
 
96
 
97
  raw_frames.append(np.array(img.convert("RGB")))
98
+ time.sleep(0.035)
99
 
100
  browser.close()
101
 
102
+ print(f"๐ŸŽฌ Encoding {len(raw_frames)} square frames (720x720) to H.264 replay.mp4...")
 
 
103
  writer = imageio.get_writer(
104
  str(output_mp4),
105
  fps=25,
 
112
  writer.close()
113
 
114
  size_kb = round(output_mp4.stat().st_size / 1024, 1)
115
+ print(f"[โœ“] SUCCESS: 1:1 Square (720x720) Replay saved to: {output_mp4} ({size_kb} KB)")
116
  return output_mp4
117
 
118
  if __name__ == "__main__":
119
+ generate_square_canvas_replay()
replay.mp4 CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:e134174f3b67ec14f619b2aa5388f3400543c4b3ac8bdcf0697a8ced77079861
3
- size 84384
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:603cd6ef2258e042f78086778645ecdd7def3fa72edf660e9c7d2e3025fd25dc
3
+ size 89969