Nodes/Pulse Studio/Pulse Render
ComfyUI Node

Pulse Render

The executor that makes long MiniMax H3 films survivable

By Addis-Pulse-Studio·Created about a month ago·Updated 15 days ago· 2
Pulse Render
  • timeline
  • model
  • vae
  • audio_vae
  • model_fl2va
  • video
  • frames
  • audio
  • segment_paths
  • report
schema_version3.0.0
cache_modeauto
run_dirpulseslate
run_id
save_segmentstrue
low_memorytrue
dry_runfalse
prune_unusedfalse
use_reference_audiofalse
seam_treatmentaudio+colour

H3's ceiling is ~15 seconds per call. Pulse Render is how you get past it.

MiniMax H3 generates one window per call, trained up to 362 frames - about 15 seconds at 24fps. Anything longer means splitting the timeline into chained windows, and that's a completely different job from a single generation. That job is what Pulse Render does: it walks a PULSE_TIMELINE from a Pulse Slate node, renders one window per H3 call, writes each finished segment to disk, and stitches the result.

The thing that makes it worth your time isn't the rendering - it's the segment cache. Every window lands in ComfyUI/output/<run_dir>/<run_id>/ as it completes, with a manifest fsynced before the next window starts. The practical consequences:

  • Kill the render at window 9 of 12, requeue, and windows 0–8 load from disk while 9–11 render.
  • Edit one shot, and only the window holding it re-renders - at its original seed.
  • Change the seed, the steps, or the upstream patch chain, and everything goes (all three change what comes out).
  • Seeds are derived from the set of shots in a window, so inserting a shot at the top doesn't reroll every window after it.

The inputs that matter

The required timeline comes from Pulse Slate. model is the ref2va checkpoint with every patch already applied upstream - this node samples with the model it's handed, so a patch applied downstream does nothing at all. vae and audio_vae are both required, because H3 always builds a joint audio+video latent. Everything else is choices:

  • cache_mode - auto reuses whatever's unchanged; force_rerender ignores the cache; reuse_only refuses to render anything and aborts naming the first missing window. That last one is how you assemble a final cut without regenerating a frame.
  • dry_run - the report and nothing else: no sampling, no decode, no file writes. This is the habit that saves you: a wrong reference binding renders successfully and hands you a well-formed film of the wrong person. The report's per-shot ordinal map is how you catch it before spending GPU time.
  • low_memory (default on) - accumulates assembled frames as 8-bit and releases VRAM between windows. The finished video is assembled by stream-copying the segment files, so a twelve-window film never exists in RAM.
  • seam_treatment - where two windows meet, the container seam is gapless by construction, but the two sides are independent generations: a score that restarts, a level that steps. audio level-matches the join with an equal-power dip; audio+colour also grades a window's opening toward the previous exit frame, decaying over 12 frames. off is for A/B-ing - colour matching occasionally makes things worse.
  • use_reference_audio - on a lip_sync shot, H3's audio is a re-synthesis of your recording (close, but not your take). This muxes the original recording into the film instead. Off by default, because it silences everything the model scored around the voice; reversible without re-rendering.
  • run_dir / run_id - folder naming; an empty run_id derives from the timeline, so the same project reopens into the same folder across sessions.

Outputs: video, frames, audio, segment_paths (a string listing the run folders - feed those to PulseBench for the speed table), and report.

The patch chain is upstream, and it's not optional in practice

Pulse Render consumes a patched MODEL and doesn't patch anything itself. The documented chain, wired by you:

UNETLoader → SpectrumApplyMiniMaxH3 (history_storage: system_ram)
  → PatchSageAttentionKJ → Sol-Attn → Pulse Slate / PulseRender

Order matters: Sol-Attn must come after the Sage patch, or Sage shadows it and you get no speedup - and the graph still runs and still produces output. Wire patches into both model inputs (model for references, model_fl2va for anchors). Every approximation on the incoming model is detected and folded into the cache key, so changing tau_start re-renders the affected segments instead of silently reusing ones rendered at the old sparsity.

And system_ram is not a speed setting. On a 32 GB card, Spectrum storing history in system RAM is what makes a 362-frame window fit at all; set it to vram and a full-length window likely OOMs. The node warns - on its face and in the console - when it finds no attention or offload patch, but never blocks. Running unpatched is a legitimate choice; the warning just makes it a choice instead of an accident.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/Addis-Pulse-Studio/comfyui-pulse-studio

Restart ComfyUI. Nothing to pip install - zero dependencies, just torch/numpy/Pillow/av from your ComfyUI, which must be 0.30.0+ with H3 support in the host build. Grab the weights from Comfy-Org/MiniMax-H3 into the minimax/ subfolders (ref2va DiT ~20 GB, fl2va ~20 GB if you use anchored continuity, text encoder ~15 GB, two VAEs). They carry the geofenced MiniMax H3 Community License - no US, EU, UK or Korea - and on Linux/macOS the example graphs' loaders show red until you re-pick each file (Windows-authored backslash paths).

Honest troubleshooting

The long-form path (PulseSlate_LongForm.json) runs end to end on real hardware - a >15 s multi-window render completed on the author's box - but the seam-by-seam listening pass is explicitly not written down yet. Treat seam quality as unconfirmed; if a seam sounds wrong, that's seam_treatment and the report, not a fault in your install. And if save_segments is off, there are no segment files to join - take frames + audio instead, or turn it back on.

CategoryAddisPulse/H3

Inputs (15)

NameTypeDefaultDescription
timelinePULSE_TIMELINEFrom a Pulse Slate node. Carries the compiled plan, the window seeds and the reference digests the segment cache keys on.
modelMODELThe ref2va checkpoint, with every attention and memory patch already applied upstream. This node samples with the model it is handed, so a patch applied downstream would do nothing.
vaeVAE
audio_vaeVAE
schema_versionSTRING3.0.0Which widget layout this node was saved with. Written by the node, read at load time to restore values by name. Do not edit.
cache_modeCOMBOauto'auto' reuses any window whose content, seed and patch chain are unchanged. 'force_rerender' ignores the cache. 'reuse_only' refuses to render anything and aborts if a window is missing -- for assembling a final cut without regenerating a frame.
run_dirSTRINGpulseslateFolder under ComfyUI/output that holds run folders.
run_idSTRINGWhich run folder to resume into. Empty derives it from the timeline, so the same project reopens into the same folder across sessions -- and a seed change still reuses that folder.
save_segmentsBOOLEANtrueWrite each window to disk as it finishes. This is what makes a killed render resumable. Turning it off gives up the cache.
low_memoryBOOLEANtrueAccumulate assembled frames as 8-bit and release VRAM between windows. The finished video is assembled by joining the segment files, so with this on a twelve-window film never exists in RAM.
dry_runBOOLEANfalseProduce the report and nothing else: no sampling, no decode, no file writes. A wrong reference binding renders successfully and gives you the wrong film -- this is how you catch it first.
prune_unusedBOOLEANfalseDelete segments in this run folder that the current timeline no longer references. Off by default: yesterday's segments are what make flipping back to yesterday's edit free.
use_reference_audioBOOLEANfalsePut the lip_sync reference recordings into the finished film instead of the audio H3 generated. H3 always synthesises its own track, and on a lip-sync shot that track is a re-synthesis of your recording -- close, but not your take. Off by default because it silences everything the model scored around the voice; the generated audio is still written to each segment's .flac either way, so this is reversible without re-rendering.
seam_treatmentCOMBOaudio+colourWhat to do where two windows meet. The container seam is already gapless -- this is about the two sides being independent generations: a score that restarts, a level that steps, a grade that drifts. 'audio' matches the opening level to the previous tail and puts a 20-50ms equal-power dip across the join. Sample count is preserved exactly, so nothing drifts against the picture. 'audio+colour' also matches the entrance frame's per-channel mean and spread to the previous exit frame, decaying over the first frames so the correction does not simply move the cut to the next seam. 'off' is there so you can A/B it -- colour matching occasionally makes things worse.
model_fl2vaoptMODELThe First/Last-Frame checkpoint. Needed by the continuity modes that pin a frame.

Outputs (5)

NameTypeDescription
videoVIDEO
framesIMAGE
audioAUDIO
segment_pathsSTRING
reportSTRING