H3 Prepare Video · Auto Size & Length
H3 Prepare Video does the boring arithmetic H3 refuses to do
- video
- reference_frames
- source_audio
- width
- height
- h3_length
- source_frames
- fps
- summary
- prepared_video
Every H3 video graph starts with the same chores, and every one of them has cost somebody an hour: the source is 30 fps and H3 wants 24, the dimensions aren't divisible by 32, and the clip is 6.2 seconds when H3's frame grid only accepts 17n+5. Do it wrong and you get smeared audio, a distorted aspect ratio, or a cryptic length error after the model has already loaded.
H3 Prepare Video · Auto Size & Length is a CPU-only node that does all of it. No sampling, no model loading, no GPU. It's dull in the best way. If you've seen it titled Resolution budget & output duration in a shared character-swap workflow, it's the same node - same class, same sockets, currently shipping inside H3 Relay rather than the separate labs-video-prep package.
What you give it
video - a native ComfyUI VIDEO input, so load with a Load Video node. And resolution, a two-way choice: 480 caps you at 0.5 megapixels, 768 at 1.0 MP.
Optionally duration_seconds. Leave it at 0 for the whole clip, or give it a target and it keeps the beginning, trimming the tail to the nearest 17n+5 length at 24 fps: 5s → 124 frames, 6s → 141, 7s → 175. It never invents frames to reach your number - if the source ends earlier, you get the source.
What it gives back
Nine outputs, and unlike most multi-output nodes you'll actually use several:
reference_frames- the prepared IMAGE batch, padded with repeated final frames up to the H3 window length, ready to wire as the video reference.prepared_video- a VIDEO wrapper of the unpadded timeline, for previewing what the model will actually see.source_audio- the soundtrack trimmed to the unpadded video length, never stretched to fill padding.source_frames- the real (unpadded) frame count. This is the one people forget. Wire it to the windowed edit node'ssource_count, or to the trim node after a single-window decode, and you avoid shipping the padding into your output.h3_length,width,height,fps- integers and a float, for the graphs that need explicit dimensions or lengths rather than inferred ones.summary- a human-readable string: dimensions and megapixels against the budget, frame count and duration, the H3 length with its repeated tail count, and whether it cropped to the 32-pixel grid.
How it works, since the details matter
It shells out to ffprobe to read display dimensions, honouring sample aspect ratio and rotation metadata, then to ffmpeg to normalize to 24 fps, scale with Lanczos and center-crop to the 32-pixel grid. It searches the grid for the canvas closest to your source aspect ratio without exceeding the pixel budget - which is why you don't get the usual independently-rounded-each-axis result that blows past the cap on one side. Scale first, then crop: nothing gets stretched. The intermediate is a lossless FFV1 file read back through ComfyUI's VIDEO API, so trim and crop wrappers upstream are respected rather than bypassed.
A useful side effect: the preview and audio keep the unpadded timeline while reference_frames carries padding, so you can see what the model gets versus what you'll keep.
Installing - and the one real requirement
The node ships in H3 Relay:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/akatz-ai/h3-relay.git
Manager → H3 Relay → restart also works, and it needs current ComfyUI (the pack declares 0.32.0 minimum) with the native VIDEO API. ffmpeg and ffprobe must be on your PATH. That's the most common failure by a wide margin, and it's an environment problem, not a node problem - if ComfyUI runs inside a venv or container, the binaries have to be visible inside that environment. ffmpeg -version in the same shell you launch ComfyUI from is the test.
If you had the older standalone labs-video-prep pack installed, remove it. H3 Relay keeps the class identifier, widget order and sockets, so saved workflows load without rewiring - but the stale package can shadow the current implementation.
Unlike the rest of the pack, this node pulls no models and submits no jobs, which makes it the safest thing in the repo to add to an existing install.
Snags
Could not prepare the uploaded video:plus FFmpeg's own stderr - usually an unsupported container, a missing audio track (it maps0:a:0?optionally, so silent sources are fine), or a corrupt upload.- Bizarre target dimensions - check the source for rotation or non-square pixel metadata. The node compensates for both, but a file with contradictory tags will produce a canvas you didn't expect.
- A long-clip note in the summary past 362 frames - that's the author saying out loud that you're beyond H3's documented ~5–15 second trained range and memory use is unverified. Believe it.
- The output looking softer than your source - that's the resolution budget doing its job.
768exists for a reason; use it when the shot needs the detail.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | — | |
| resolution | COMBO | 480 | 480 = up to 0.5 megapixels; 768 = up to 1.0 megapixel. Automatically upscale/downscale near the source aspect ratio, with a small centered crop to H3's 32-pixel grid. |
| duration_secondsopt | FLOAT | 0.00–149.66 | 0 = full clip. Otherwise keep the beginning and trim the tail to the nearest 17n+5 window at 24 fps: 5s → 124 frames, 6s → 141, 7s → 175. Never extend beyond the source; actual duration is shown in the summary. |
Outputs (9)
| Name | Type | Description |
|---|---|---|
| reference_frames | IMAGE | — |
| source_audio | AUDIO | — |
| width | INT | — |
| height | INT | — |
| h3_length | INT | — |
| source_frames | INT | — |
| fps | FLOAT | — |
| summary | STRING | — |
| prepared_video | VIDEO | — |