# Offline kit: exact-frame assembly from video shots

This kit includes runnable source code, original geometric inputs and a recorded 22-frame local fixture. It does not generate MiniMax H3 video. Use your installed Node.js, FFmpeg and ffprobe; their executables are not bundled.

## 1. Extract and prepare

Open a shell in the extracted folder containing `run-recipe.mjs`, `frame-budget.mjs` and `original-inputs.mjs`. No website checkout or package installation is needed.

```sh
node --test frame-budget.test.mjs encoded-negative-cases.test.mjs
node run-recipe.mjs --out ./my-new-inputs-01
```

Every output directory must be new. The second command creates 25 original PNGs, three SVG designs and a preparation status with `mediaExecuted:false`. It does not encode video, contact a provider or download software. Pure tests are not media-execution evidence.

## 2. Read the recorded example without running tools

Open `media-runs/actual-small-root-20261017-02/`:

| File | What to inspect |
| --- | --- |
| `assembled-review.mp4` | The actual 22-frame positive result |
| `media-execution-receipt.json`, `run-status.json` | Recorded local execution and finite checks |
| `tool-versions.json`, `command-log.json` | Actual versions and 48 successful tool events |
| `original-input-manifest.json` | The 25 original PNG definitions; before/after hashes are in the receipt |
| `shot-a.probe.raw.json`, `shot-b.probe.raw.json`, `shot-c.probe.raw.json` | Unmodified source-probe observations |
| `decoded-inventory.json`, `edl.actual.json`, `frame-map.json` | Source timing, integer shot budgets and every selected output frame |
| `expected-marker-proof.json`, `output-probe.json` | Source/frame marker identity and the decoded output grid |
| `negative-media/` | Three actual controlled negative MP4s, probes and rejection records |

The run is dated **17 October 2026** and used Node v24.18.0, FFmpeg 6.0 and ffprobe n4.4.1. Human playback and perceptual review were not performed. This is a tiny local technical fixture, not a model-quality result or a 204-second encode.

## 3. Understand the input and output contract

The original inputs contain 8 images for A, 10 for B and 7 for C. Encoding/decoding produced 8, 10 and 8 frames: C repeats its final input image through concat. It is not a newly drawn 26th input.

- A: observed `24000/1001` fps and time base `1/48000`.
- B: 40 ms PTS spacing and time base `1/51200`.
- C: nonzero origin, with PTS `2.00, 2.04, 2.12, 2.24, 2.28, 2.36, 2.40, 2.44` seconds.

Do not replace source PTS with nominal FPS. C's raw `pkt_duration` observations remain 40 ms. Under the declared `active-at-or-before-no-interpolation` policy, a nonterminal frame's hold window is **derived from the next observed PTS**, not relabeled as an observed packet duration. The final frame requires a real positive duration observation.

The EDL binds each source SHA, source-relative start and integer output-frame budget. The recorded budgets are **7 + 7 + 8 = 22** at `24/1` fps, for exactly `11/12` seconds. Zero-based cut boundaries are **6/7** and **13/14**. The policy may repeat or drop images; it does not synthesize new motion or silently change speed.

## 4. Run a fresh small media example

Use another nonexistent output directory and replace the tool paths with your local executables:

```sh
ALLOW_LOCAL_MEDIA_EXECUTION=1 node run-recipe.mjs --out ./my-new-media-run-01 --execute-media --ffmpeg /absolute/path/to/ffmpeg --ffprobe /absolute/path/to/ffprobe
```

The explicit switch enables local encoding and decoding. The fixture uses 96×64 inputs, serial calls, single-thread settings, timeouts and bounded buffers. It requires the recorded filters plus FFV1/libx264 capabilities; a different build can fail. It does not install tools or make model/provider requests.

## 5. Check the result and its controls

Require all of these, rather than trusting the displayed duration alone:

- Exactly 22 decoded images, frame observations and packets.
- All output PTS/DTS on the `24/1` grid; every normal and terminal frame has duration `1/24`.
- All 22 source/frame markers agree with the map, including both sides of each cut.
- The three actual controls each produce only their intended validator issue.

| Control | Controlled defect | Sole observed issue |
| --- | --- | --- |
| `short-21-of-22.mp4` | 21 images/frames/packets | `OUTPUT_FRAME_COUNT` |
| `wrong-cut-image.mp4` | Wrong image at zero-based frame 7 | `OUTPUT_FRAME_ID_MISMATCH` |
| `bad-terminal-duration.mp4` | Same images, PTS and encoded payload; last sample 1,000→500 ticks at time base `1/24000` | `OUTPUT_TERMINAL_DURATION` at frame 21 |

The terminal control changes actual MP4 timing bytes, not probe JSON. Its mutator supports only this fixture's single-track, nonfragmented layout with no edit list or composition reordering and final `moov` after `mdat`. Encoder/probe failures or unsupported layouts are not accepted negative results.

The recorded positive MP4 SHA-256 is:

```text
3b624e031f6a082e2ac2ae89b8c36cb91873bd67c5d64f8c5fa1427059db96f1
```

Keep inputs, raw probes, EDL, frame map, marker proof and command logs with the output. A new tool build can change encoded bytes; compare the actual timing and identity checks as well as hashes. Timing correctness does not establish attractive motion, matching lighting, sound synchronization or narrative continuity. Review those separately on your own footage.

## License and references

The original code and fixtures include `LICENSE.txt`. FFmpeg and ffprobe binaries are not bundled. The example has no font, external image or model-output dependency. References: [FFmpeg concat](https://ffmpeg.org/ffmpeg-filters.html#concat), [fps](https://ffmpeg.org/ffmpeg-filters.html#fps-1), [setpts](https://ffmpeg.org/ffmpeg-filters.html#setpts_002c-asetpts).
