all works

minimax-h3 in comfyui, with the graph attached

comfyuivideoworkflow
model
minimax-h3
tool
comfyui
a title card: the words minimax-h3 workflow set in thin white type on a violet gradient

this is the graph i actually run, cleaned up and attached at the bottom. one
reference image goes in, ten seconds of video comes out, and the audio comes out
of the same sampler rather than getting bolted on afterwards. there is a second
stage that continues the shot past ten seconds, and an optional upscale hanging
off the side.

download the workflow — drag
the json onto the comfyui canvas.

what you need on disk

the loader nodes carry their download urls, so comfyui will offer to fetch most
of this the moment the workflow opens. if you would rather do it by hand:

file goes in
minimax_h3_ref2va_pruned_int8_convrot.safetensors models/diffusion_models/
qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors models/text_encoders/
minimax_h3_video_vae_fp16.safetensors models/vae/
minimax_h3_audio_vae_fp32.safetensors models/vae/
minimax_h3_fl2v_turbo_4step_v1.1_768p_comfyui_bf16.safetensors models/loras/

all of them live under Comfy-Org/MiniMax-H3 on huggingface. two vaes is not a
mistake — one decodes the frames, the other decodes the sound, and both hang off
the same latent. the text encoder is a qwen3-vl checkpoint, so in CLIPLoader
the type has to be set to minimax, not to whatever it defaults to.

the diffusion model and the text encoder are both quantised builds. that is the
only reason this fits on a normal card at all.

custom nodes

everything with MiniMaxH3 in the name is core, and so is SamplerCustomAdvanced
and friends. the rest comes from packs:

  • PathchSageAttentionKJ — kjnodes. the typo is upstream's, not mine.
  • ComfyMathExpression — the comfy math pack. it does the seconds-to-frames sum.
  • ResolutionSelector, StringConstantMultiline, Video Slice,
    MiniMaxH3TurboLoRA, MiniMaxH3MemoryEfficientSageAttentionPatch,
    SpectrumApplyMiniMaxH3 — i genuinely don't remember which pack each of these
    came from. if a node loads red, manager → install missing custom nodes will
    find them by type name.

the sage attention patcher needs the sageattention python package installed in
the same environment as comfyui. if it throws on the first run, that is usually
why — set the node to disabled and the graph still works, just slower.

driving it

four things to touch, and nothing else:

  1. the reference image. it decides the subject, the palette, the framing and
    the art style. the model holds onto it hard, which is the point.
  2. the prompt. the text box wired into prompt. describe the shot, not the
    picture — the picture is already handled by the reference.
  3. seconds. the PrimitiveInt set to 10.
  4. the frame size. ResolutionSelector at 16:9 and 1.3 megapixels gives
    1344×768, which is what the 768p turbo lora was trained at.

then queue. stage one writes through the savevideo named ..._stage1.

the frame count is not arbitrary

this is the part that cost me an evening. you cannot just type a number into
length. the model wants a frame count where (frames − 5) divides by 17, and
anything else gets rejected. that collapsed math node is doing:

max(5, round(seconds * 24)) + (5 - (max(5, round(seconds * 24)) % 17)) % 17

which is 24 fps, rounded up to the next legal value. ten seconds becomes 243
frames, five seconds becomes 124. leave the node wired and change the seconds
instead.

going past ten seconds

the second stage ships muted. unmute Video Slice, the GetVideoComponents
next to it, the second sampler group and its savevideo, and you get a
continuation: Video Slice takes the last two seconds of stage one, those frames
go in as a reference video, and the original still image goes in alongside them
so the character doesn't drift.

the important bit is the second text box. write what happens next in it. if
you paste the first prompt in again the model starts the same motion over from
the beginning, and you get ten seconds of someone turning their head twice.

one honest inconsistency: SpectrumApplyMiniMaxH3 sits in both sampler
subgraphs, muted in stage one and active in stage two. that is how it ended up on
my machine and i left it that way rather than quietly change behaviour you can't
see. set both the same before you compare takes.

the upscale

realesrgan x2 hanging off the stage-one video, muted by default. it is a single
pass over the frames rather than diffusion, so next to the sampling time it costs
almost nothing — and because it is a separate branch, the original file gets
written either way. needs RealESRGAN_x2plus.pth in models/upscale_models/.

before you ask

the seeds in the attached file are zeroed and the prompt boxes hold neutral
placeholder text — it is a skeleton to fill in, not a recipe to rerun. keep the
seed fixed while you're iterating on wording, or you'll never work out whether
the change came from the prompt or the noise.