HirModel commited on
Commit
ebf1ba6
·
verified ·
1 Parent(s): 3ea98cb

Upload 15 files

Browse files
HF_RUNTIME_FIX_RECEIPT_6.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # HF Runtime Fix Receipt 6 — PATCHED8 Preview Rehydration
2
+
3
+ ## Status
4
+ HELD for preview-repair packet generation.
5
+
6
+ ## Fault observed
7
+ The app route processed the video and generated trace receipts, but both top video preview panes showed blank/NaN preview behavior in the Gradio UI.
8
+
9
+ ## Cause class
10
+ Gradio `Video` upload/preview behavior was unreliable for this Space runtime even though the uploaded video was readable by OpenCV and the route completed.
11
+
12
+ ## Patch applied
13
+ - Replaced the left upload `gr.Video` control with a `gr.File` video uploader so file intake is stable and path-bound.
14
+ - Added `coerce_uploaded_path()` to support Gradio file/video payload variants.
15
+ - Added `make_preview_mp4()` to create a browser-stable MP4 preview without mutating the canonical source video.
16
+ - Added upload-time preview rehydration via `video_input.change(...)`.
17
+ - Returned the browser-safe preview MP4 after route execution instead of returning the raw uploaded path.
18
+ - Kept source hashing, atomization, frame extraction, scene detection, trace-stack construction, receipt generation, and packet creation intact.
19
+
20
+ ## Boundary preserved
21
+ The preview MP4 is a display artifact only. The canonical source remains the uploaded video hash and source capsule authority.
22
+
23
+ ## Expected result
24
+ After upload, the right preview pane should populate with a playable browser-safe MP4. After route execution, the same preview pane should remain populated while receipts/tables/gallery are generated.
HF_Substrate_Video_Atomization_Runtime_v0_1_PATCHED8.zip.sha256 ADDED
@@ -0,0 +1 @@
 
 
1
+ 58ad79d19f38a0a9a7ad5c86b87fae64355dbb80b05cc07ce3d55decd2333c06 /mnt/data/HF_Substrate_Video_Atomization_Runtime_v0_1_PATCHED8.zip
README.md CHANGED
@@ -12,9 +12,9 @@ license: cc-by-nc-sa-4.0
12
  short_description: Video atomization and trace-stack rehydration
13
  ---
14
 
15
- # Substrate Video Atomization Runtime v0.1
16
 
17
- Upload a short video and run a source-bound atomization route.
18
 
19
  This Space demonstrates Video Atomization, Trace-Stack Rehydration, and Data Hologram formation as a Substrate Mesh runtime surface. The uploaded video is not treated as a monolithic compressed payload. Instead, the runtime hashes the source, samples frame atoms, detects scene intervals, records motion deltas, applies trace capsules, stacks the traces, and returns a rehydrated review surface with an HIR × OAM receipt.
20
 
 
12
  short_description: Video atomization and trace-stack rehydration
13
  ---
14
 
15
+ # Substrate Video Atomization Runtime v0.1.1
16
 
17
+ Upload a short video and run a source-bound atomization route. v0.1.1 adds browser-safe preview rehydration while preserving source-bound receipts.
18
 
19
  This Space demonstrates Video Atomization, Trace-Stack Rehydration, and Data Hologram formation as a Substrate Mesh runtime surface. The uploaded video is not treated as a monolithic compressed payload. Instead, the runtime hashes the source, samples frame atoms, detects scene intervals, records motion deltas, applies trace capsules, stacks the traces, and returns a rehydrated review surface with an HIR × OAM receipt.
20
 
__pycache__/app.cpython-313.pyc ADDED
Binary file (24.8 kB). View file
 
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import cv2
3
  import json
4
  import hashlib
 
5
  import tempfile
6
  import zipfile
7
  from datetime import datetime, timezone
@@ -38,7 +39,7 @@ def _install_gradio_schema_guard() -> None:
38
  _install_gradio_schema_guard()
39
 
40
 
41
- APP_TITLE = "Substrate Video Atomization Runtime v0.1"
42
  BOUNDARY_NOTE = (
43
  "This demo performs source-bound video atomization and trace-stack rehydration. "
44
  "It is not video compression, not a codec replacement, and not a physical hologram generator. "
@@ -96,6 +97,82 @@ def make_run_dir() -> Path:
96
  return Path(tempfile.mkdtemp(prefix=f"video_atomization_{stamp}_"))
97
 
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  def classify_pressure(motion_delta: float, scene_threshold: float) -> str:
100
  if motion_delta >= scene_threshold * 1.6:
101
  return "STRAINED_SCENE_BREAK_PRESSURE"
@@ -154,7 +231,8 @@ def create_run_packet(run_dir: Path, packet_name: str = "video_atomization_run_p
154
 
155
 
156
  def atomize_video(video_path, sample_every_seconds=1.0, scene_threshold=32.0, max_frame_atoms=72):
157
- if not video_path:
 
158
  empty = pd.DataFrame()
159
  return (
160
  None,
@@ -181,15 +259,15 @@ def atomize_video(video_path, sample_every_seconds=1.0, scene_threshold=32.0, ma
181
  scene_threshold = max(safe_float(scene_threshold, 32.0), 1.0)
182
  max_frame_atoms = max(safe_int(max_frame_atoms, 72), 1)
183
 
184
- source_hash = sha256_file(video_path)
185
- file_size = os.path.getsize(video_path)
186
- filename = os.path.basename(video_path)
187
 
188
- cap = cv2.VideoCapture(video_path)
189
  if not cap.isOpened():
190
  empty = pd.DataFrame()
191
  return (
192
- video_path,
193
  {"error": "OpenCV could not read this video. Try MP4/H.264, WebM, or MOV."},
194
  empty,
195
  empty,
@@ -428,8 +506,10 @@ def atomize_video(video_path, sample_every_seconds=1.0, scene_threshold=32.0, ma
428
  "Trace stack formed. Data hologram review surface generated. Human validation required."
429
  )
430
 
 
 
431
  return (
432
- video_path,
433
  source_capsule,
434
  frame_df,
435
  scene_df,
@@ -450,7 +530,7 @@ custom_css = """
450
  with gr.Blocks(title=APP_TITLE, css=custom_css) as demo:
451
  gr.Markdown(
452
  """
453
- # Substrate Video Atomization Runtime v0.1
454
 
455
  Upload a short video and run a source-bound atomization route.
456
 
@@ -463,11 +543,23 @@ This v0.1 Space demonstrates the source-bound data-hologram layer.
463
  )
464
 
465
  with gr.Row():
466
- video_input = gr.Video(
467
- label="Upload source video",
468
- sources=["upload"]
 
 
 
 
 
 
 
469
  )
470
- video_output = gr.Video(label="Source video preview")
 
 
 
 
 
471
 
472
  with gr.Row():
473
  sample_every_seconds = gr.Slider(
@@ -525,6 +617,12 @@ This v0.1 Space demonstrates the source-bound data-hologram layer.
525
  with gr.Tab("Download Run Packet"):
526
  run_packet = gr.File(label="Download JSON receipts and sampled frame atoms")
527
 
 
 
 
 
 
 
528
  run_btn.click(
529
  atomize_video,
530
  inputs=[video_input, sample_every_seconds, scene_threshold, max_frame_atoms],
 
2
  import cv2
3
  import json
4
  import hashlib
5
+ import subprocess
6
  import tempfile
7
  import zipfile
8
  from datetime import datetime, timezone
 
39
  _install_gradio_schema_guard()
40
 
41
 
42
+ APP_TITLE = "Substrate Video Atomization Runtime v0.1.1"
43
  BOUNDARY_NOTE = (
44
  "This demo performs source-bound video atomization and trace-stack rehydration. "
45
  "It is not video compression, not a codec replacement, and not a physical hologram generator. "
 
97
  return Path(tempfile.mkdtemp(prefix=f"video_atomization_{stamp}_"))
98
 
99
 
100
+ def coerce_uploaded_path(uploaded) -> str | None:
101
+ """Return a filesystem path from Gradio File/Video payload variants."""
102
+ if uploaded is None:
103
+ return None
104
+ if isinstance(uploaded, (str, os.PathLike)):
105
+ return str(uploaded)
106
+ if isinstance(uploaded, dict):
107
+ for key in ("path", "name", "orig_name"):
108
+ value = uploaded.get(key)
109
+ if value and os.path.exists(str(value)):
110
+ return str(value)
111
+ return None
112
+ name = getattr(uploaded, "name", None)
113
+ if name and os.path.exists(str(name)):
114
+ return str(name)
115
+ return None
116
+
117
+
118
+ def make_preview_mp4(video_payload, target_dir: Path | None = None) -> str | None:
119
+ """Create a browser-stable MP4 preview path without mutating the source video."""
120
+ video_path = coerce_uploaded_path(video_payload)
121
+ if not video_path or not os.path.exists(video_path):
122
+ return None
123
+
124
+ if target_dir is None:
125
+ target_dir = Path(tempfile.mkdtemp(prefix="video_atomization_preview_"))
126
+ target_dir.mkdir(parents=True, exist_ok=True)
127
+ preview_path = target_dir / "source_video_preview.mp4"
128
+
129
+ # First try a fast stream-copy with +faststart. This fixes many browser/Gradio
130
+ # preview failures without the cost of a full transcode.
131
+ faststart_cmd = [
132
+ "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
133
+ "-i", video_path,
134
+ "-map", "0:v:0", "-map", "0:a?",
135
+ "-c", "copy",
136
+ "-movflags", "+faststart",
137
+ str(preview_path),
138
+ ]
139
+ try:
140
+ subprocess.run(faststart_cmd, check=True, timeout=90)
141
+ if preview_path.exists() and preview_path.stat().st_size > 0:
142
+ return str(preview_path)
143
+ except Exception:
144
+ pass
145
+
146
+ # Fallback: browser-safe H.264/AAC transcode. This is slower, but bounded to
147
+ # preview generation and still keeps the original file as the canonical source.
148
+ transcode_cmd = [
149
+ "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
150
+ "-i", video_path,
151
+ "-map", "0:v:0", "-map", "0:a?",
152
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "23",
153
+ "-pix_fmt", "yuv420p",
154
+ "-c:a", "aac", "-b:a", "128k",
155
+ "-movflags", "+faststart",
156
+ str(preview_path),
157
+ ]
158
+ try:
159
+ subprocess.run(transcode_cmd, check=True, timeout=240)
160
+ if preview_path.exists() and preview_path.stat().st_size > 0:
161
+ return str(preview_path)
162
+ except Exception:
163
+ pass
164
+
165
+ # Last resort: return the source path so the rest of the route still holds.
166
+ return video_path
167
+
168
+
169
+ def prepare_video_preview(video_payload):
170
+ preview_path = make_preview_mp4(video_payload)
171
+ if not preview_path:
172
+ return None, "Preview waiting for source video."
173
+ return preview_path, "Preview rehydrated from source-bound upload. Source remains canonical authority."
174
+
175
+
176
  def classify_pressure(motion_delta: float, scene_threshold: float) -> str:
177
  if motion_delta >= scene_threshold * 1.6:
178
  return "STRAINED_SCENE_BREAK_PRESSURE"
 
231
 
232
 
233
  def atomize_video(video_path, sample_every_seconds=1.0, scene_threshold=32.0, max_frame_atoms=72):
234
+ source_video_path = coerce_uploaded_path(video_path)
235
+ if not source_video_path:
236
  empty = pd.DataFrame()
237
  return (
238
  None,
 
259
  scene_threshold = max(safe_float(scene_threshold, 32.0), 1.0)
260
  max_frame_atoms = max(safe_int(max_frame_atoms, 72), 1)
261
 
262
+ source_hash = sha256_file(source_video_path)
263
+ file_size = os.path.getsize(source_video_path)
264
+ filename = os.path.basename(source_video_path)
265
 
266
+ cap = cv2.VideoCapture(source_video_path)
267
  if not cap.isOpened():
268
  empty = pd.DataFrame()
269
  return (
270
+ make_preview_mp4(source_video_path, run_dir),
271
  {"error": "OpenCV could not read this video. Try MP4/H.264, WebM, or MOV."},
272
  empty,
273
  empty,
 
506
  "Trace stack formed. Data hologram review surface generated. Human validation required."
507
  )
508
 
509
+ preview_path = make_preview_mp4(source_video_path, run_dir)
510
+
511
  return (
512
+ preview_path,
513
  source_capsule,
514
  frame_df,
515
  scene_df,
 
530
  with gr.Blocks(title=APP_TITLE, css=custom_css) as demo:
531
  gr.Markdown(
532
  """
533
+ # Substrate Video Atomization Runtime v0.1.1
534
 
535
  Upload a short video and run a source-bound atomization route.
536
 
 
543
  )
544
 
545
  with gr.Row():
546
+ video_input = gr.File(
547
+ label="Upload source video file",
548
+ file_types=["video", ".mp4", ".mov", ".webm", ".mkv"],
549
+ type="filepath"
550
+ )
551
+ video_output = gr.Video(
552
+ label="Source video preview / rehydrated browser-safe MP4",
553
+ format="mp4",
554
+ interactive=False,
555
+ show_download_button=True
556
  )
557
+
558
+ preview_status = gr.Textbox(
559
+ label="Preview Status",
560
+ value="Upload a video to rehydrate a browser-safe source preview.",
561
+ interactive=False
562
+ )
563
 
564
  with gr.Row():
565
  sample_every_seconds = gr.Slider(
 
617
  with gr.Tab("Download Run Packet"):
618
  run_packet = gr.File(label="Download JSON receipts and sampled frame atoms")
619
 
620
+ video_input.change(
621
+ prepare_video_preview,
622
+ inputs=[video_input],
623
+ outputs=[video_output, preview_status]
624
+ )
625
+
626
  run_btn.click(
627
  atomize_video,
628
  inputs=[video_input, sample_every_seconds, scene_threshold, max_frame_atoms],