# FROZEN TIME — complete runbook **One ordinary photo of an athlete → a photoreal shot where time stops and the camera flies around them.** Status: **PROVEN.** First run landed usable. Two shots shipped from this method. Everything below is measured on real runs, not theory. --- ## 0 · READ THIS FIRST You are most likely an LLM that someone has pointed at this document. This file is self-contained: it carries every setting, every command, the exact prompt, and every failure already paid for. You should not need anything else. Read all of it before acting. The order of the steps is load-bearing, and three of the gotchas cost real money if skipped. ### The code this file refers to — download it, do not rewrite it `frozen_camera.py` and `frozentime` are referenced throughout. **They exist. Fetch them; never synthesise them from the snippets in §6, which are excerpts, not a runnable script.** | | | |---|---| | everything, one file | `https://frozen-time.pages.dev/files/frozen-time-kit.zip` | | the Blender renderer | `https://frozen-time.pages.dev/files/frozen_camera.py` | | the five-stage CLI | `https://frozen-time.pages.dev/files/frozentime` | | the prompt | `https://frozen-time.pages.dev/files/seedance_prompt.txt` | | a worked job file | `https://frozen-time.pages.dev/files/job_example.json` | **Meshy has no CLI in this kit.** Higgsfield's exact commands are in §7; for Meshy, use the web UI with the settings in §5, or its own published API. Do not invent endpoints. **If you cannot reach the network, say so and stop** — do not reconstruct the renderer from §6. ### The intake — four things, before anything else | # | thing | example | |---|---|---| | 1 | **Project / shot id** | `R118` | | 2 | **The source frame** | a path to a `.png` or `.jpg` | | 3 | **The coaching point** — the one thing the shot must reveal | `"the sideways trunk lean as they align before the jump"` | | 4 | **Where the athlete is in the frame** | a pixel bounding box, `x0,y0,x1,y1` | | 2b | *or, if no frame exists yet* — **a clip + a timestamp**, and you cut the frame in §4 | `clip.mp4` @ `12.4s` | If any of the four is missing, **ask for it and stop.** #3 decides where the camera lands. #4 is required by the Blender solve — a blank bounding box kills the job three steps later with no useful error message. ### The two rules that cost money 1. **Two steps are billable. Everything else is free and re-runnable.** Iterate in the free part; arrive at the paid part already right. 2. **Never spend without showing the operator a live quote first, and never proceed without an explicit approval that matches that quote.** See §10. --- ## 1 · WHAT THE SHOT IS > An ordinary single-camera frame of an athlete. Time freezes at the coaching beat. The camera > flies around them to reveal the mechanic — on the reference run, the sideways trunk lean of a > fast bowler aligning before the jump. Then it holds. It is a **coaching instrument**, not an effect. The camera goes where a coach would want to stand, and holds there long enough to read. If the move does not reveal the fault, the shot has failed, however pretty it is. The trick that makes it work: **the AI video model is never asked to invent a camera move.** It is handed a grey clay video that already contains the exact move, and told to repaint it photoreal. The camera path is solved in Blender for free; only the paint costs money. --- ## 2 · WHAT YOU NEED | | | |---|---| | **A source frame** | 9:16, ≥1024px on the short side, the athlete isolated, minimal motion blur | | **Meshy** | paid account, `meshy-7`, image-to-3D. Web UI is sufficient. | | **Blender** | **5.2**. No plugins needed. | | **Higgsfield** | an account with `seedance_2_5` access | | **ImageMagick 7** | `magick` (not `convert`) — for the bounding-box solve | | **ffmpeg** | frame grabs and the final encode | | **A deblurrer** *(optional, paid)* | only if the frame carries motion blur — see §4. Not counted in §10. | Everything except Meshy and Higgsfield is free. A deblurring tool is the one optional extra. --- ## 3 · THE TWO LANES **Lane A — manual.** Meshy's web UI, the Blender script by hand, Higgsfield's UI or CLI. Anyone with the two accounts can do this. Follow §4–§8 in order. **Lane B — the harness.** A CLI, `frozentime`, drives all five stages and keeps a per-shot ledger. ⛔ **The gate is NOT in this script.** `frozentime` calls the billable verb directly and expects `meshy` and `higgsfield` on `PATH` to be **gate wrappers** that refuse to spend until a live quote exists and `MESHY_GO` / `HF_GO` match it. Those wrappers are not in the kit. Point `frozentime` at the plain vendor CLIs and it will spend unguarded, with no quote shown. Write your own gate, or use Lane A. See §10 and §14. **Lane A is the source of truth.** The harness is a convenience over it. If the two ever disagree, Lane A is right. --- ## 4 · STEP 1 — THE FRAME *(free)* Pull the frame at the coaching beat: ```bash ffmpeg -ss -i clip.mp4 -frames:v 1 -q:v 1 frame.png ``` ⛔ **`-ss` goes AFTER `-i`.** Fast-seek lies — put `-ss` first and you get a keyframe near your timestamp, not your timestamp. **Motion blur is the enemy of Step 2.** A bowler's arm at delivery is the blurriest thing in the frame, and Meshy will smear it. Deblur the *clip* before grabbing the frame — Topaz Video AI's Motion Deblur (Themis 2) is one option, and it is a paid product; any competent deblurrer will do, and a sharp frame needs none. Then crop to isolate the athlete: no umpire, no fielders, no second body. ⛔ **Upgrade the reference image before you generate.** A raw frame crop is never good enough to be ``. Enhance it first — an image model, or a manual clean-up — get it approved, and only then quote. A soft photo makes a soft shot, and you will have paid for it. **Record two things — the next steps need them:** - the frame's pixel dimensions - the athlete's bounding box in pixels, `x0,y0,x1,y1` Reference run: frame `768 × 1376`, bbox `[95, 280, 672, 1100]`. **Crop aspect must match the output aspect.** A 0.75 crop feeding a 9:16 output made every camera fit overflow the frame. If you are delivering 9:16, crop 9:16. --- ## 5 · STEP 2 — MESHY: one image → rough 3D *(💰 billable, gate 1)* Upload the frame to Meshy image-to-3D. Only these settings matter: | param | value | why | |---|---|---| | `ai_model` | `meshy-7` | current | | `ultra_mode` | `true` | better geometry — though it is decimated to 8% later, so see §10 for the cheaper option | | `should_texture` | `true` | | | `texture_resolution` | `2k` | | | **`pose_mode`** | **`""` — empty, the default** | ⛔ **preserves the photo's pose. Forcing A-pose or T-pose destroys the entire shot.** | Export **GLB** — one file, mesh and texture together, and Blender fixes the Y-up→Z-up flip on import. FBX splits the textures out and gives you more to lose. **What to expect.** Meshy's own docs warn against dynamic action poses, and pre-run research predicted a bowler mid-delivery would come out melted. **It did not.** Clean limbs, separate fingers, kit folds, real shoes. **But only on the side the photo saw.** The opposite side is invention. This is fine — the mesh is a camera-path carrier, not a hero asset. Nobody ever sees it. Reference asset: 999,863 verts / 1,921,758 tris, 3 PBR maps, no rig, no animation. **Known defect:** Meshy fused three ball-sized blobs at the bowler's hand. Iterative RANSAC (radius ≈ 0.036 m) finds all of them; keep one dense sphere, delete the rest. --- ## 6 · STEP 3 — BLENDER: the camera move *(free, re-run as often as you like)* This is the whole craft of the pipeline and it costs nothing. Iterate here, not at Step 4. Run headless: ```bash blender -b -noaudio --python frozen_camera.py -- render --job job.json ``` Six things matter. ### 6.1 · Decimate to 8% ```python m = obj.modifiers.new("d", "DECIMATE") m.ratio = 0.08 # 1.92M → 154k tris ``` **Rough beats detailed.** Creators feeding block-outs to AI video models consistently report that too much geometric detail makes the model copy stiff geometry instead of animating naturally. Meshy being crude is a *feature* here. ### 6.2 · Solve frame 1 onto the reference photo Do not eyeball this. Render the silhouette with `film_transparent`, measure its alpha bounding box with `magick -trim`, and iterate distance + aim until it lands on the photo's box: ```python R *= h / TARGET_H # scale by height ratio upp = (36.0 * R / LENS) / FRAME_H # world units per pixel aim = aim - right * ((TCX - cx) * upp) + Vector((0, 0, (TCY - cy) * upp)) ``` Converges in **4 passes**. Reference result: bbox `597×820` centred `(384,690)` against a target of `577×820` at `(384,690)` — height and centre exact, width 3.5% wide from pose residual. Good enough; the match cut lands clean. ### 6.3 · Find the azimuth — do not guess it Two separate jobs. Do not confuse them: - **The match angle** — where the shot *starts*, so frame 1 cuts cleanly from the real footage — is found by the machine: sweep azimuth and match the silhouette's **aspect ratio** to the photo's. - **The reveal angles** — where the shot *goes* — are picked by a **person**, by eye, off a 12-view contact sheet rendered at 30° steps. Reference run: the photo's subject aspect was `0.704`; the sweep gave `az 120° → 0.731`, `az 130° → 0.666`. Answer: **123°**. The eyeball guess had been 145° — **the solve beat it by 22°.** ⛔ **Aspect-ratio solving cannot tell an angle from its mirror twin.** Render both twins next to the photo before calling either one the start. A mirrored start was caught by eye once and would otherwise have shipped. ### 6.4 · Ground the world — the decision that makes or breaks it **A figure floating in a grey void kills the generation.** Most of the frame then has zero optical flow, so the video model gets no camera data for ground, fence or trees. It reads the shot as *the subject spinning on a turntable*, not *a camera orbiting a world*. Two fixes were tried. **Only one works.** | approach | verdict | |---|---| | Camera-project the source photo onto ground + backdrop cards | ❌ **Fails.** Smears into streaks past ~20° of travel, and clones a ghost of the athlete onto the grass. | | A large procedural ground plane + sun + cast shadow | ✅ **Works.** Real horizon, real parallax, and the shadow stays a readable camera cue even at the bird's eye. | ```python bpy.ops.mesh.primitive_plane_add(size=3000, location=(ctr.x, ctr.y, FLOOR)) # two-octave noise → colour ramp, scales 220 and 1400, muted greens # sun at 50° elevation, energy 3.0 # world background: flat overcast blue-grey ``` - Ground plane at **3000 units** — anything smaller and its edge walks through frame as a false horizon. - Render in **EEVEE**, not Workbench, or the ground material never shows. (The silhouette solves in 6.2 use Workbench + FLAT deliberately, for a clean alpha.) ### 6.5 · Time it like a motion-control rig A quartic ease-out looks snappy on paper and reads as a **jerk** — it starts at infinite acceleration. Use a solved cubic bezier instead, Newton-iterated the way CSS does it: ```python SWING = bez(0.40, 0.00, 0.10, 1.00) # brief accel, high peak, long graceful settle DOLLY = bez(0.30, 0.00, 0.18, 1.00) # trails the swing by 4 frames RISE = bez(0.22, 0.00, 0.30, 1.00) # leads the swing by 2 frames ``` **Measured profile** (26-frame whip): start velocity `0.08`, peak at frame 7, half the move done by frame 9, 90% by frame 16, end velocity `0.015`. No snap at either end. **Split the channels.** Elevation *leads* by 2 frames, the dolly *trails* by 4 — the camera arrives, *then* the push resolves. That offset is what stops the move reading as one rigid slide. **Nothing sits dead.** A 1.2% radius drift runs through the holds. ### 6.6 · The beat sheet that shipped | frames | | position | |---|---|---| | 1–10 | hold | **the match frame** — az 123°, level, 50mm. Dead still, so the cut can land. | | 10–36 | whip | az 0°, 26° down-angle, close | | 36–58 | hold | | | 58–84 | whip | az −165°, **82° elevation** — the bird's eye | | 84–144 | hold | with drift | Total: **6.00 s at 24 fps, 1080×1920.** For the bird's eye, **don't move the aim point to compose** — use the camera's **frustum shift**, which is exact and needs no axis guessing: ```python cd.shift_x += (cx - FRAME_W / 2) / FRAME_H cd.shift_y -= (cy - FRAME_H / 2) / FRAME_H ``` Ramp the shift in across the second whip so earlier beats stay unshifted. Fitting loops that move the *aim point* diverge easily on sign errors. Prefer measuring in pixels and correcting with frustum shift — or verify the sign on iteration 0 before trusting the loop. ### 6.7 · The job file `frozen_camera.py` is fully parameterised by JSON. This is the exact job that produced the reference run: ```json { "mesh": "mesh.glb", "reference": { "image": "source_frame.png", "width": 768, "height": 1376, "bbox": [95, 280, 672, 1100] }, "output": "guide.mp4", "fps": 24, "resolution": [1080, 1920], "lens_mm": 50.0, "decimate_ratio": 0.08, "beats": [ { "name": "match", "fit": "match", "azimuth": 123.0, "elevation": 0.0, "radius_mult": 1.000, "aim_height_frac": 0.10, "hold_frames": 10, "whip_in_frames": 0 }, { "name": "profile_whip", "fit": "none", "azimuth": 0.0, "elevation": 26.0, "radius_mult": 0.579, "aim_height_frac": 0.22, "hold_frames": 22, "whip_in_frames": 26 }, { "name": "birdseye", "fit": "frustum", "azimuth": -165.0, "elevation": 82.0, "radius_mult": 0.901, "aim_height_frac": 0.00, "fit_target_height_frac": 0.72, "hold_frames": 60, "whip_in_frames": 26 } ], "clip_guard": { "enabled": true, "margin_frac": 0.01, "scale": 0.35 } } ``` ⛔ **Only the match beat's azimuth is re-solved per job.** `radius_mult` and `aim_height_frac` for every beat carry over from the reference run — re-check them on the contact sheet for any athlete of different proportions. **`clip_guard` tells you when a beat is cropping the athlete's limbs.** It flagged frames 20–70 on the reference run and it was right — the shipped shot inherited a leg crop because the warning was ignored. Listen to it. `frozen_camera.py` subcommands, all taking `--job`: | | | |---|---| | `render` | the full pipeline: solve, ground, animate, render, encode | | `contact-sheet` | azimuth/elevation sweep montage, for a person to pick beat angles by eye | | `solve-azimuth` | sweep azimuth, match the reference bbox aspect ratio, report the best angle | --- ## 7 · STEP 4 — HIGGSFIELD SEEDANCE: paint it real *(💰 billable, gate 2)* ### 7.1 · Upload the media FIRST ⛔ **This is not optional.** Passing local file paths to `generate cost` / `generate create` makes the CLI upload them inside the call, and it **times out** — `request failed (no response received)`. This failed twice before it was diagnosed. Upload separately, then pass UUIDs: ```bash higgsfield upload create ./guide.mp4 --json # → video uuid higgsfield upload create ./reference.png --json # → image uuid ``` ### 7.2 · Quote, then run ```bash # 1. QUOTE — free. Always do this first, and always show the operator the number. higgsfield generate cost seedance_2_5 \ --prompt "$(cat seedance_prompt.txt)" \ --mode omni_reference --duration 6 --resolution 1080p --aspect-ratio 9:16 \ --image --video # → 54 credits # 2. RUN — only after the operator approves that exact number. HF_GO=54 higgsfield generate create seedance_2_5 \ --prompt "$(cat seedance_prompt.txt)" \ --mode omni_reference --duration 6 --resolution 1080p --aspect-ratio 9:16 \ --image --video # 3. WAIT higgsfield generate wait ``` **`seedance_2_5` in `omni_reference` mode does 1080p.** Older notes claim it caps at 720p — that is stale. The live schema says `480p / 720p / 1080p`. **Check the live schema, never the note.** **Cost scales with duration, and prompt length does not move it** — 6 s at 1080p 9:16 = **54 credits**, 4 s = 36. Resolution also moves the price; quote every combination you actually intend to run rather than scaling a number yourself. --- ## 8 · THE PROMPT ### 8.1 · The exact text that ran ``` Use the grey clay reference video as the only reference for the camera: its movement, path, speed, shot-size changes, framing and blocking. Follow it exactly, frame for frame. Do not change the shot structure. Do not add cuts. The clay video governs camera only — it does not govern colour, material or appearance. Use the reference image for everything that is seen: the man, his clothing, the grass field, the fence, hedgerow, trees and overcast sky, and the blue cone on the ground. The scene is frozen in time — a bullet-time freeze-frame. 100% frozen physics, zero temporal movement anywhere in the environment. Infinite shutter. The man is arrested mid-delivery at front-foot contact: trunk tilted to his side as he aligns before the jump, bowling arm high, trail leg extended behind, front foot planted. His trunk angle and spine tilt are the subject of the shot and stay exactly as they are. The camera alone travels, at normal speed, through the stopped world — a rapid orbital fly-around of a stationary point in space, exactly as the reference video describes. Ground, fence, trees and sky parallax correctly with the camera. His face does not need to match the reference image and may stay soft and loosely defined; body shape, pose, clothing and the field are what must hold. Photoreal, overcast late-afternoon light, matching the reference image's colour and grain. Avoid: the subject moving, re-posing or continuing the delivery; grey clay or stone material on skin or fabric; the background sliding or dissolving; camera cuts; speed ramps; subtitles; logos; watermarks. ``` ### 8.2 · The reusable template Substitute `{teaching}` with the coaching point from the intake. Match the pronouns to the athlete in the frame. ``` Use the grey clay reference video as the only reference for the camera: its movement, path, speed, shot-size changes, framing and blocking. Follow it exactly, frame for frame. Do not change the shot structure. Do not add cuts. The clay video governs camera only — it does not govern colour, material or appearance. Use the reference image for everything that is seen: the athlete, their clothing, and the field around them. The scene is frozen in time — a bullet-time freeze-frame. 100% frozen physics, zero temporal movement anywhere in the environment. Infinite shutter. The athlete is arrested mid-action: {teaching}. This is the subject of the shot and stays exactly as it is. The camera alone travels, at normal speed, through the stopped world — a rapid orbital fly-around of a stationary point in space, exactly as the reference video describes. Ground, fence, trees and sky parallax correctly with the camera. The face does not need to match the reference image and may stay soft and loosely defined; body shape, pose, clothing and the field are what must hold. Photoreal, matching the reference image's colour and grain. Avoid: the subject moving, re-posing or continuing the action; grey clay or stone material on skin or fabric; the background sliding or dissolving; camera cuts; speed ramps; subtitles; logos; watermarks. ``` ### 8.3 · Why each block is there 1. **Name the video's job and its limits.** The clause *"The clay video governs camera only — it does not govern colour, material or appearance"* is what stops grey clay bleeding onto skin and fabric. 2. **Name the image's job.** Everything that is seen. 3. **Freeze the world, not the athlete.** *"frozen in time — a bullet-time freeze-frame. 100% frozen physics… Infinite shutter."* 4. **Say what the shot is about.** *"Trunk angle and spine tilt are the subject of the shot."* Without this the model has no idea which detail is load-bearing. 5. **Release what doesn't matter.** *"The face does not need to match and may stay soft."* This frees model attention for the mechanic — and it is honest, because the far side of the head is invention anyway. 6. **A short, specific avoid list.** Only failures *this* shot can actually have. ### 8.4 · Language rules the research corpus agreed on - ⛔ **Never phrase negatively.** `no camera movement` fails; `the camera remains still` works. One documented user stacked 36 negative clauses and it still drifted. - ⛔ **"Statue" is the wrong word.** It is tagged to marble and bronze in training data and pulls the render toward stone. Use **"frozen in time"** / **"bullet-time freeze-frame"**, which are tagged to the VFX look you want. - **Keep the camera clause in its own sentence,** apart from the stillness clause. Never stack two moves in one clause. - **Cut the wardrobe inventory.** The model can see the image; reciting *"white striped polo, blue shorts"* eats attention that should be policing physics. Version 1 of the prompt did this; version 2 dropped it and improved. --- ## 9 · ADDENDUM — COACHING ARROWS IN 3D ⛔ **Not reproducible from this kit.** The renderer ships with the `annot_*` handling described below, but the tool that turns a coach's drawn strokes into those objects is not included. Treat this section as the design of a proven feature, not as runnable instructions. A coach draws arrows on rendered reference stills. Strokes are **back-projected through the saved cameras** to the body's depth — one world direction per force — and built as flat arrow glyphs in the scene. Objects named `annot_*` are special to the renderer: - no decimate, own material, no shadow - **billboarded** to the animated camera every frame (+X along the screen projection of `annot_dir`) - a quick-out / slow-back nudge (`annot_amp`, `annot_period`, `annot_phase`) - a show range (`annot_show`) - body-only solves; frustum fits see the pull arrows With `annot_only: true`, the job renders an **arrows-only ProRes 4444 alpha pass** from the same camera — pure emission, so the brand colour comes out exact. ⛔ **Send the video model the CLEAN guide.** Lay the alpha pass over the finished shot in your NLE. **Never ask the video model to paint arrows.** ⛔ **Arrows are a rendered component fed to the model as a reference, never a flat overlay slapped on afterwards.** A glass-textured, photoreal arrow card plus the upgraded reference with arrows placed; both go in as references. **Gotchas paid for on this beat:** 1. Blender's glTF export adds `NORMAL` + `TEXCOORD` to a `POSITION`-only Meshy mesh → sparkle. Export with `export_normals=False` after `normals_make_consistent`. 2. Workbench `show_shadows` on a dense mesh = speckle. 3. The reference crop must share the output aspect (see §4). Cost of this beat: 39 credits at 720p. --- ## 10 · COST AND THE SPEND GATES ### Per shot | | config | credits | |---|---|---| | Mesh | ultra + 2k texture | 35 | | Video | 6 s, 1080p, 9:16 | 54 | | **Total** | | **89** | Everything between the two — angles, contact sheets, the camera move, the grey guide render — is **free** and re-runs as often as you like. ### An unproven 37% saving The reference run paid for a 2k texture and then rendered the mesh grey. | | shipped | lean | |---|---|---| | mesh | 35 cr (ultra + 2k texture) | **20 cr** (`--no-ultra --no-texture`) | | video | 54 cr (6 s 1080p) | **36 cr** (4 s 1080p) | | | **89 cr** | **56 cr** | The texture is thrown away by the clay guide, and ultra buys geometry that gets decimated to 8%. 720p is cheaper again — quote it, do not assume a ratio. ⛔ **Unproven.** Prove the lean mesh on a known frame before making it the default. ### The gates Both billable steps sit behind a wrapper that **blocks the billable verb until a live quote exists and an approval token matches it exactly:** - Meshy → `MESHY_GO=` - Higgsfield → `HF_GO=` ⛔ **The token must equal the live quote.** Change the duration or the resolution and the old approval dies — re-quote and get a new one. ⛔ **Never bypass a gate.** A bypass environment variable exists and must never be used. ⛔ **Never test a guard by running the live billable command.** Test the function, never the outward verb. That mistake once fired a real paid job with no approval. --- ## 11 · GOTCHAS, COLLECTED | | | |---|---| | **ffmpeg** | `-ss` goes **after** `-i` for accurate seeking. Fast-seek lies. | | **Blender 5.2** | `Action` has no `.fcurves`. Set `bpy.context.preferences.edit.keyframe_new_interpolation_type` before inserting keys. | | **Blender 5.2** | `BLENDER_EEVEE_NEXT` does not exist — the enum is `BLENDER_EEVEE`. | | **Blender 5.2** | `FFMPEG` is not valid in `image_settings.file_format`. Render a PNG sequence, encode with ffmpeg afterwards. | | **Blender** | The ground material needs EEVEE. Workbench will not show it. | | **Blender** | glTF export adds NORMAL/TEXCOORD to a POSITION-only mesh → sparkle. `export_normals=False`. | | **ImageMagick 7** | `magick`, not `convert`. | | **Meshy** | `pose_mode` empty. Forcing A/T-pose destroys the shot. | | **Meshy** | May fuse duplicate blobs at the hands. Iterative RANSAC finds them. | | **Higgsfield** | Upload media separately and pass UUIDs, or the call times out. | | **Higgsfield** | Model capability notes go stale. Read the live schema. | | **Solve** | Aspect-ratio azimuth solving cannot distinguish mirror twins. Check both. | | **Solve** | Fitting loops that move the aim point diverge on sign errors. Use frustum shift. | | **Crop** | Reference crop aspect must equal output aspect. | --- ## 12 · KNOWN DEFECTS ON THE REFERENCE RUN All three fold into a single re-run. 1. **The athlete re-poses in the first second.** By the front beat the trail leg has drawn in and he stands more upright than the tape. The freeze then holds — but the exact delivery shape has drifted, and **the lean was the lesson.** Next attempt: a shorter first whip, or state the pose more concretely in the prompt. 2. **No ball in the hand.** Fix this **upstream** — edit the source frame so the ball is visible, then re-run. **Never ask the video model to invent a ball.** 3. **The front beat crops the legs.** `clip_guard` flagged frames 20–70 and was correct; the warning was ignored and the output inherited it. Re-frame that beat. ### The adversarial review, scored A pre-run adversarial pass predicted five failures. Two were right, and the fixes for those two are what made the run work — so the pass paid for itself. | predicted | outcome | |---|---| | Background disintegration from the void | **Prevented** — by grounding the render (§6.4). Was a real risk. | | Face hallucination on the front beat | **Happened, and was fine** — the face was explicitly released in the prompt. | | Motion-vector leak, the freeze breaking | **Partly happened** — the re-pose above. The one open defect. | | Clay texture bleed onto skin | **Prevented** — by dropping "statue" and scoping the clay video to camera only. | | Match-cut rupture | **Did not happen.** Frame one cuts clean. | Its headline number — *"under 8% chance of a usable run"* — was wrong. The run was usable first time. **Treat an adversarial reviewer's probabilities as priors to act on, not as measurements.** Its reasoning was worth every credit; its numbers were not evidence. --- ## 13 · WHERE EVERYTHING LIVES **One rule: a shot lives with its project.** Nothing about a deliverable sits in a scratch directory. ``` /frozentime// ← the shot. everything. state.json which stage it is on, what it cost, every path ledger.jsonl every attempt: quoted, approved, ran, failed work/ contact sheet, the grey guide, intermediates /.md ← decisions, defects, version-controlled. / ← the METHOD, not the work. FROZEN_TIME.md frozentime frozen_camera.py seedance_prompt.txt ``` A second shot on the same project is a **second `` folder beside the first** — never a second job id in a scratch tree. **The card is the ledger of decisions; the folder is the ledger of files.** Keep both, always. --- ## 14 · THE HARNESS CLI `frozentime` — one command over the five stages. Every subcommand takes `--reel` (the project id) and, for a second shot on the same project, `--job-id`. ``` frozentime init --reel R118 --frame frame.png \ --teaching "the sideways trunk lean" --bbox 95,280,672,1100 frozentime mesh # 💰 GATE 1 — Meshy image-to-3D, needs MESHY_GO frozentime angles # free — auto-solve the match azimuth + contact sheet, or record a pick frozentime guide # free — render the grey camera move locally frozentime generate # 💰 GATE 2 — Higgsfield Seedance, needs HF_GO frozentime file # free — copy into the project folder, print the card block frozentime status # where the job is, what is next, what it has cost ``` Useful flags: | command | flag | | |---|---|---| | `mesh` | `--no-ultra` `--no-texture` | the lean config from §10 | | `mesh` | `--pose-mode` | leave empty — forcing a pose destroys the shot | | `angles` | `--count 12` `--elevations 0,30,60` | contact-sheet sweep | | `angles` | `--hint ` | disambiguates the mirror-twin problem | | `angles` | `--pick --beat --elevation ` | record a picked reveal angle | | `guide` | `--beats @beats.json` `--lens` `--decimate` | override the proven beat sheet | | `generate` | `--duration` `--resolution` `--aspect-ratio` `--prompt-file` | | | `file` | `--update-card` | append the block into the shot card | | `status` | `--all` | every job on disk | Root and output directories are overridable by environment variable — see the top of the script. --- ## 15 · VERIFICATION CHECKLIST Before calling a shot done, check every line against the **artifact**, not against your memory of what you asked for: - [ ] Frame 1 of the output lands on the source photo — the match cut is clean - [ ] All camera beats followed, in order, with real motion blur on the whips - [ ] Ground, fence and background **parallax** correctly — no sliding, no dissolving - [ ] No grey clay or stone material anywhere on skin or fabric - [ ] The freeze holds — the athlete does not continue the action - [ ] **The coaching point is legible.** If the mechanic is not readable, the shot failed. - [ ] `clip_guard` warnings addressed, not ignored - [ ] Output resolution, fps and duration are what was quoted - [ ] Ledger written: quoted, approved, ran - [ ] Shot card updated with the decision and any defect --- ## 16 · PROVENANCE The method was assembled from a 14-lane research hunt — roughly 5,900 lines, every documented prompt carrying the URL it was fetched from. The closest public precedents found: | | | |---|---| | **Cricket batsman, 270° orbit, full JSON prompt** | `x.com/CurieuxExplorer/status/2043231863397867741` · 12 Apr 2026 · Seedance 2.0 | | **Volleyball spike, frozen orbit + release** | `x.com/altphotos_pl/status/2042936345325084788` · 11 Apr 2026 · 192k views | | **The clay-pass approach, from the vendor** | `x.com/higgsfield_ai/status/2073150339004715494` · 3 Jul 2026 · 146k views | | **Depth-video-driven full-body motion** | `x.com/MrLarus/status/2080323396865241237` · 23 Jul 2026 | The `shot / subject / visual_details.time_release / cinematography / audio` JSON shape from the first of those is the ancestor of the prompt in §8. --- *Pipeline proven 05 September 2026. Runbook compiled 09 September 2026.*