Spaces:
Running on Zero
Running on Zero
Commit History
-
Apply the thermo-review survivors (app side) Running
The chain is three links — begin absorbed the accidental prepare_cpu boundary (same process, one recording, one part fewer). The generation result crosses the fork as a typed RunResult. merge_rrd_parts requires every part non-empty and lands atomically via os.replace. pump owns its worker's lifetime: an early consumer close requests the stop sentinel and joins with a bounded window, and run_gpu closes its phase generators before disconnecting the recording. Vendored: space-streaming@c8893d6. Validated end-to-end locally: 479 s, all 19 stages once, merged rrd from exactly three parts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>260a292 -
Apply the simplify-pass survivors (app side)
Preview stills now slice the canonical clip instead of re-decoding the upload — the old path indexed raw frames, which diverge whenever the start time is non-zero (wrong stills in the diffusion grid). One skip predicate guards both module-level loads, so smoke mode is GPU-free for the preview decoder too. 'Generating six views' and 'Publishing the result' each announce once. STAGES is assembled from the label registries plus a shared denoise-label formatter, so a renamed label can no longer silently lose its progress count; the annotation context takes its joint subset from simplecv's COCO_17_IDX instead of assuming contiguous ids. Vendored: pipeline space-streaming@d2ac77a. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>9ae2cb2 -
Trim the GPU reservation to the preloaded pipeline's measured need
258 s of GPU-link time on a real slice; 330 keeps ~70 s of headroom and brings the 1.5x-billed admission request from 585 to 495 seconds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>734c249 -
Preload the generation stack at startup, per the ZeroGPU pattern
Vendored from space-streaming@c1b702c: load_pipeline memoizes embedding-backed loads (device key normalized — prepare_run's 'cuda:0' and the warm call's 'cuda' are one entry), warm_generation_models() populates the cache at import, and the app warms it beside the preview decoder. Every ZeroGPU fork inherits the loaded weights instead of re-reading ~11 GB inside the allocation ('models must be placed on cuda at the root module level' — the documented pattern). Validated locally: the loading stage went from 18 s to instant on a cache hit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>3352901 -
Vendor the ZeroGPU media-prep gate
space-streaming@4a618ae: media prep (skeleton cache residency, GPU batch resizes) falls back to the host when SPACES_ZERO_GPU is set — the slice's restricted NVML asserts in torch's allocator as the pool grows. The prior deploy failed at 'Loading skeleton conditioning' with exactly that assert. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>aee0938 -
Track simplecv past the jaxtyping-cap fix; restore jaxtyping 0.3
examples-monorepo#141 relaxed the stale <0.3 cap, so the workspace returns to jaxtyping 0.3.11 and drops the typeguard shim dependency. typing-extensions stays <4.16: that cap is pyserde's own current requirement, not a stale one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>5298d66 -
Depend on simplecv from the examples-monorepo for skeleton data
simplecv = { git, subdirectory = packages/simplecv, rev = ab4f8441 } — viz.py now builds the keypoint annotation context from coco_133's own names, colors, and links instead of a mirrored copy. The solver required numpy >=2 (was <2), ultralytics >=8.3 (8.2.42 pinned numpy<2), jaxtyping 0.2.36 (pyserde caps <0.3), and typing-extensions <4.16. Full pipeline validated on the new environment: identical framing confidence (0.991), radius 2.583 vs 2.591 from the tracker bump, six views + rrd produced, 19/19 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>db4dfa4 -
Adopt simplecv's coco_133 palette and screen-space keypoint dots
The joint colors and skeleton links now mirror simplecv's data/skeleton/coco_133.py (face blue, left green, right orange) — mirrored rather than imported, since simplecv requires numpy>=2 and this frozen ZeroGPU environment sits on numpy 1. Dots use ui-point radii: image-pixel radii vanished under the skeleton lines once the clip was scaled into its pane. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>9f1e93d -
Give the ViTPose keypoints a COCO-17 annotation context
Named, side-colored joints (left blue, right orange) with the COCO skeleton drawn between them, low-confidence joints filtered out, labels on hover only — the stage previously rendered seventeen identical dots. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>b84a490 -
Show stage progress and elapsed time in the status banner
Every banner label now carries its position in the fixed 19-stage run and a running clock: 'Estimating 2D keypoints. (5/19 - 1:23)'. The Run click is stamped into RunSpec so the clock survives the ZeroGPU fork; unknown labels (failures, stop notices, smoke phases) pass through untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c57dcae -
Label every stage honestly and drop the remaining idle transfers
Vendored from space-streaming@191002e (stage-start announcements, GPU BiRefNet with cached model, device-resident skeleton cache, no dead DiT offload or per-view cache flushes). App side: labels key on the new ':start' events — the old payload events fired at stage end, so ViTPose ran under 'Tracking the subject' and BiRefNet's 41 s ran under 'Fitting the SMPL-X body'. New banners cover foreground masks, skeleton rendering, model loading, VAE encode, skeleton loading, and view decoding; the working-clip prep announces itself before the first GVHMR stage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>edc854a -
Cut ~100 s of per-run glue and label denoise steps at their start
Vendored from pipeline space-streaming@2f581d5: GPU turbo-LoRA merge, two-frame decode verifies (three full-clip decodes dropped), ultrafast lossless GVHMR encode, batched GPU skeleton crop/resize, and an on_denoise_step_start hook. App side: the step label and diffusion blueprint now fire before a step's first forward pass, so the first ~65 s of denoising no longer runs under the previous phase's banner. sync_vendor.sh now shields the app-owned rerun_streaming.py and viz.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>dda92e4
-
Trim the GPU reservation to measured need
Four ZeroGPU runs measured 313-334 s against a 420 s request, and admission charges a large slice at 1.5x — the padding alone raised every visitor's quota bar by 45 s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>85d320e -
Offer the finished recording as a download
Each link's recording now tees into a footerless FileSink beside the live binary stream (binary_stream first, then set_sinks with both — the call replaces the sink set). publish concatenates the four part files into one recording; footerless parts are what make that a single valid RRD instead of one with duelling manifests. A hidden DownloadButton appears with the merged file when the run finishes, and each new run hides it again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>df58091 -
Surface run failures in the status banner and toast
An error mid-run left only a bare Error chip: the toast for uncaught exceptions carried no message and dismissed itself. show_error puts the exception text in the toast, and the GPU and publish links now write a persistent Failed line into the status banner before raising. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>f5d0a1f -
Link the title's Rerun to rerun.io
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>6324ae7 -
Reveal the recovered body while the generator loads
The mesh and camera streamed at the motion tail but stayed invisible: the motion layout has no 3D pane and the diffusion grid replaced it seconds later, leaving a minutes-long model-loading window staring at stale detections. The motion tail now switches to a body layout — the canonical world looping beside the projected source overlay — and the denoise hook brings in the preview grid when the first step actually lands. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>982b332 -
Drop the explicit queue configuration
The hardcoded concurrency limit serialized every visitor behind one run. ZeroGPU already schedules GPU slots per Space and admits against each visitor's own quota, so Gradio's defaults are the right layer to decide queueing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>131fa87
-
Tuck start time and seed into an Advanced settings accordion
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>b000fc7 -
Show the body mesh and project it onto the source clip
The canonical world gains the translucent SMPL-X mesh (exoego pattern: static faces with albedo alpha 90, streamed vertices) with the joints and bones reading through it, and the moving source camera — pose recovered per frame by a rigid Kabsch fit of the incam body onto the canonical one, K_fullimg as its pinhole. The source video moves under world/camera/video so the viewer reprojects the mesh and skeleton onto the person natively (arkitscenes technique; world content listed explicitly in the pane's contents). Result layout matches the approved reference: wide 3D pane and source on top, six clean views in one row. Median reprojection error against ViTPose observations: ~10 px at 704-pixel width, with a 1e-7 m rigid-fit residual. Implemented by Codex against the reviewed spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>fd37678 -
Keep the examples as a thumbnail gallery
A second example input turns the gallery into a labeled table, which reads far worse in the narrow control column than one row of four tiles. The start_time reset it carried goes: a stale nonzero start on an example clip fails the probe with a clear message instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>e0fb844 -
Source the examples from the model repository's Pexels clips
All twenty clips under AntResearch/4DAnyone data/source/pexels become the example gallery, four per page, instead of the one vendored clip. They mirror into the data root at boot (209 MB, seconds at hub bandwidth) pinned to the revision that carries all twenty — the model pin predates twelve of them. gr.set_static_paths serves them in place; Gradio would otherwise copy every example into its temp cache at construction. Each example also resets start_time: the clips are cut to the 121-frame contract with one frame of slack, so any later start fails the probe. Remote resolve-URLs were rejected because Gradio downloads example URLs eagerly at construction anyway — same bytes, none of the pinning or resume. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>09f33ca -
Split the app into viz, streaming runtime, and Gradio wiring
Thermo-nuclear finding 1, approved: fdanyone_app.py carried UI, ZeroGPU transport, Rerun logging, pipeline orchestration, and smoke data in one 1100-line module that run_native.py reached into for fourteen symbols. Recording-explicit log helpers and the blueprints join the timeline names in fdanyone/viz.py; the sink-agnostic runtime — spec, session, pump, hooks, phases, stop sentinel — moves to fdanyone/rerun_streaming; the app keeps only Gradio callbacks, spaces wiring, and the layout. Phases now take a RecordingStream directly, so Link loses its optional stream and stays with the only caller that needs it. Implemented by Codex against the review spec; behavior unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>2001557 -
Let generate_run consume its PreparedRun
Thermo-nuclear review: scratch cleanup lived in every caller — run_pipeline's finally, the app worker's finally — and release_run skipped the scratch discard when skeleton settlement raised. Release now happens once, inside generate_run itself, and release_run discards scratch in its own finally. Both caller-side cleanups are deleted, and lifecycle tests pin settlement + discard across success, generation failure, and settlement failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>8c3d629 -
Settle generation scratch in the worker that owns it
Four-reviewer simplify pass over the Stop change. A stopped run leaked its scratch tree: Gradio closes the generator before the sentinel stops the worker, so the worker_finished cleanup guard never fired. Releasing in the worker's own finally covers return, failure, and stop alike, and deletes the flag plus the conditional cleanup. The stop test now proves a mid-run stop deterministically instead of an abort-at-entry, and the session fixture takes data_dir instead of being duplicated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>4c983fd -
Make Stop actually halt the pipeline via a run-scoped sentinel
Gradio's cancels only closes the request generator; the pipeline keeps running on a worker thread locally and in a forked child on ZeroGPU. Stop now writes a sentinel file under the run's data dir, and the motion/denoise hooks — the only code the pipeline re-enters — raise RunCancelled when they see it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>326f401 -
Cap the source preview height
A portrait clip — the shape this demo is for — scaled to the full column width, so the preview alone ran 816px tall on a 1080p screen and pushed the start time, seed, examples, Run and the status line below the fold. Fix the preview at 360px so the input column fits one screen whatever the clip's aspect; Gradio letterboxes the video inside it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>3ec40ad -
Make the run status legible
The status Markdown rendered at body size in a block Gradio caps with an inline `overflow: auto`, so a one-line phase label sat in a 23px sliver with a scrollbar. Give it an id and style it as a banner: 1.15rem text, padding, a secondary fill, and a min-height that clears the progress overlay Gradio draws over a running event, with overflow forced back to visible. Gradio 6 moved `css` from the Blocks constructor to `launch`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>287a7db -
Adapt turbo mode to ZeroGPU and set the measured duration
Three slice incompatibilities found by live runs: no NVCUVID (PyAV skeleton decode), no torch.compile (dynamo collides with the spaces package's patched torch.cuda internals), and torchao FP8 tripping an NVML assert in torch 2.12's allocator. bf16 + SageAttention runs a denoise step in ~31 s on the half Pro 6000; a full run_gpu measured ~270 s, reserved at 420. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>e4159cf -
Describe the fork the streaming mechanics now turn on
The old text said `spaces.GPU` allocates to "this process" and that each GPU callback runs its own pipeline call. Both are now wrong, and the first was misleading before: the callback runs in a forked child, which is the whole reason a link opens its own recording and the chain passes a picklable spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>ab9682b -
Give every chain link its own recording, and one allocation to the GPU
On ZeroGPU, `@spaces.GPU` runs its callback in a forked child, and a `RecordingStream` cannot cross that fork: the SDK compares pids on flush and raises "Fork detected during flush". The app opened one stream in `begin`, on the CPU, and the first GPU link's first `read()` died on it. Nothing caught this locally because `spaces` is a no-op off a Space, so no fork ever happened and every test passed. Each link now opens its own stream under the run's token, so the viewer merges them into one recording. This costs the viewer nothing: `BinaryStream.read` already returns a whole RRD document, so what a run sends has always been a concatenation of them, and a stream per link only changes how many carry the same store id. The same fork rules out the process-local session table. The chain now carries a picklable `RunSpec`, and motion and generation share one link, because `PreparedRun` holds decoded frames and a live barrier that no pickle can carry from one worker into another — and every d…d346bdc -
Pad GPU durations until real ZeroGPU timings exist
Spark timings suggest 135s motion / ~525s generation; half a Pro 6000 is an unknown. A mid-phase allocation kill is worse than a pessimistic reservation, and only elapsed time is billed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>a3a8d5a -
Put the controls beside the viewer instead of under it
Every other Rerun Space here — mast3r-slam, mini-dpvo, moge-v2 — splits the page into a narrow controls column and a wide viewer column. This one stacked them, so on a laptop the viewer took the fold and the Run button sat below it, out of sight. The 3D rig and the six-pane grid also want width more than they want the full page. A single `gr.Row` holding `gr.Column(scale=1)` and `gr.Column(scale=3)`, the same shape moge-v2 uses. Every component and the whole event chain are untouched; only the containers around them moved, and the viewer grew from 680 to 760 to match. It stays outside the tabs, as the house rule requires: the component is created once and streams for the length of a run, and a tab switch would tear it down mid-stream. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>502143b -
Force a one-second GOP on every logged video
The web viewer decodes VideoStream through WebCodecs, and until now every clip reached it as a single 121-frame GOP: one keyframe, at sample zero. Any decoder reset a browser makes — a scrub, a loop wrap, a throttled tab, seven streams contending for one hardware decoder — then had nowhere to resync short of the very beginning, and WebCodecs answers that with "a key frame is required after configure() or flush()". `Mp4TranscodeOptions(gop_size=25)` puts a real IDR, with its own SPS/PPS, every second instead. Verified on a pipeline clip: the untouched reader emits 1 IDR and 120 P-frames; with the option it emits 5 IDRs and 116 P-frames, one keyframe per emitted chunk, `is_keyframe` set on each chunk's first row. Side by side in a browser that can decode H.264, the same reset leaves the old recording showing spinners over stale frames in all six panes while this one comes back crisp immediately. Naming `output_codec` alongside it makes the re-encode unconditional, so an upload in any c…1980bc8 -
Re-vendor fdanyone at the B-frame-free encoder
Picks up the pipeline's own `bf=0` on `write_video`, so the mp4s on disk carry no B-frames in the first place. Belt and braces: the Rerun reader strips them anyway on the way into a VideoStream, but a target video that never had them is one fewer transcode and one fewer thing to reason about. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c89f8d5 -
JPEG-compress preview images
Raw previews dominated the recording (~0.5 GB per run) and every streamed byte a visitor downloads; 85-quality JPEG cuts both ~10x. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c1a73af -
Anchor models/ and data/ ignores to the repo root
The unanchored patterns swallowed fdanyone/vendor/diffsynth/models, so the Space boot failed with ModuleNotFoundError. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>bbf3686 -
Log raw SMPL-X parameters alongside the posed body
betas static, per-frame body_pose/global_orient as tensors and transl as scalars under world/body/params — the recording carries the actual capture output, not just its visualization. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>e58a861 -
connect sink can also save the recording to disk
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>487cb7c -
Version the viewer application id per blueprint revision
The web viewer persists blueprints keyed by application id; a stale persisted layout from an earlier session silently overrides a newly sent TimePanel. Bump the id whenever the blueprints change shape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>f761190 -
Pin prebuilt sm_120 sageattention wheel for linux-64
Cross-compiled on HF Jobs from the same pinned rev; aarch64 keeps the source build. ZeroGPU's CPU boot cannot compile CUDA extensions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>0bcd7f2 -
Stream videos as VideoStream instead of AssetVideo
Mp4Reader demuxes each MP4's samples onto the duration timeline and send_chunks delivers them; samples decode as they arrive rather than after the full asset, which suits a streamed run. Motion and result blueprints now follow the duration timeline (VideoStream samples live there; every other entity was already dual-stamped), and the diffusion source pane shows decoded stills since VideoFrameReference is an AssetVideo concept. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>5f510c6 -
Parametrize smoke pacing for phase-by-phase browser validation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>b7065c8 -
Add connect sink: viewer-first live streaming for run_native
serve_grpc from a short-lived process dies before a late-connecting viewer sees data; the proven topology is a running viewer's proxy and recording.connect_grpc into it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>dc40a7b -
Extract sink-agnostic phases and add a native CLI (DPVO pattern)
open_session/source_phase/motion_phase/generate_phase yield status labels and log through whatever sink the caller bound. The Gradio callbacks wrap them with binary-stream yields; run_native.py drives the same implementation into an .rrd file, a spawned viewer, or a gRPC server, separating logging bugs from web-viewer plumbing bugs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c142fc6 -
Fix viewer wedge: stream every viewer update, never plain-return it
The component's non-streaming branch routes a returned value to WebViewer.open(value.url) — undefined for raw bytes, which is exactly 'Failed to open recording: TypeError reading length'. begin and prepare_cpu returned bytes to the streaming viewer; both are now single-yield generators so their updates ride the media-stream path. Revert the b'' substitution: stream_output drops None chunks itself (every reference example yields read() unguarded), while b'' appends a real zero-byte playlist segment. Also bump gradio-rerun and rerun-sdk to the matched 0.36.3 pair. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>1cae0aa -
Guard binary-stream reads: None chunk wedged the web viewer
BinaryStream.read() returns bytes | None; a None yielded into the gradio-rerun component reaches JS as undefined and permanently fails the recording open (TypeError: reading 'length'). Yield b'' instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>cff882e -
Make Stop safe, colour the frusta, and warn about bare python
Stop closes the running generator while the worker thread is still inside generate_run, and the finally clause then deleted that run's scratch directory out from under it. Settle only a run whose pipeline call returned; a cancelled one leaks its scratch into the ephemeral disk, which is the cheaper failure. Each frustum takes its hue from its yaw, matching the source repository's visualizer, so a camera in the 3D view and its grid pane are the same colour. The README now says to start through pixi run: conda-forge's Triton resolves a Blackwell ptxas through $CONDA_PREFIX, which only the activation sets, and without it the turbo DiT compile fails with "Cannot find ptxas-blackwell". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>9d01809 -
Retire old sessions and fix two Rerun defects the viewer found
rr.Boxes2D rejects the string "XYXY" and silently drops the whole chunk; rr.Box2DFormat.XYXY is what it parses. The source clip's VideoFrameReference was stamped only on `frame`, so the diffusion layout's source pane rendered black while `diffusion_step` was active -- the denoise hook now repeats it on both timelines, which also keeps the source aligned with the frame each preview decodes. Sessions pin a recording buffer, and a chain that errors out never reaches its last link, so retire them by age instead of by completion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>d08c7e9 -
Add ffmpeg-python: GVHMR's video readers need it
hmr4d.utils.video_io_utils imports the `ffmpeg` module, not PyAV, so the motion phase failed at its first GVHMR import. Nothing in the fdanyone package itself imports it, which is why the first pass dropped it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>c41b3bc