MiniMax H3: Multiframe Reference
Generate video from multiple still images with MiniMax H3, anchoring up to four reference frames anywhere along the timeline to control motion and composition. Ideal for creating video continuations from existing clips, forcing narrative beats at specific moments, and producing footage with synchronized native audio for cinematic or social media content.
About
This workflow demonstrates how to drive MiniMax H3 video generation with multiple image anchors placed anywhere along the timeline. The core MiniMaxH3ReferenceToVideo node takes a long-form prompt (via PrimitiveStringMultiline) and up to four reference frames, each with its own timestamp and strength (PrimitiveInt and PrimitiveFloat), to steer motion, framing, and subject continuity at specific moments. ResolutionSelector and ComfyMathExpression set clean, multiple-of-32 dimensions, while RandomNoise provides a seed for reproducibility.
Under the hood, H3 returns video and native stereo audio as model latents. VAEDecode converts the video latents to RGB frames, and VAEDecodeAudio decodes the audio stream. CreateVideo assembles frames at the chosen FPS and muxes the decoded audio; SaveVideo then writes the final file to disk. ComfySwitchNode lets you quickly enable/disable individual reference anchors or the audio path.
The workflow is grouped for clarity (User Inputs, Conditioning, Extra Image Guidance Conditioning, Video Settings, Decoding and create video), so you can focus on anchoring key frames to force narrative beats, continue an existing clip, or produce tightly timed social content with synchronized audio.
Advanced nodes like UNETLoader, CLIPLoader, VAELoader, BasicScheduler, SamplerCustomAdvanced, and BasicGuider are included for compatibility and potential extension, but the default H3 path works out of the box. If you want to customize dimensions beyond the presets, remove the ResolutionSelector and drive width/height directly (PrimitiveInt), keeping both divisible by 32 for stable decoding.
What you provide
- Reading the workflow
Runs in ComfyUI. This workflow can't run on this page. Open it in Comfy Cloud with everything loaded, or download it for your own ComfyUI.
Try in CloudInside the workflow
A read-only preview of the node graph. Open it in Comfy Cloud or download it to edit the nodes.
Loading the graph
Open full-size workflow preview- Author
- ComfyUI
Requires custom nodes
- Reading the workflow
Use this workflow from code
Generated from the workflow graph and inputs when possible; stored examples are shown otherwise. Review credentials and endpoints before running code, which may incur charges.
What you need
- Runs on
- Comfy Cloud
- Key
- COMFY_API_KEY
Needs a paid Cloud plan and credits.
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"92": {
"class_type": "SaveVideo",
"inputs": {
"codec": "auto",
"filename_prefix": "video/MiniMax_H3",
"format": "auto",
"format.codec": "auto",
"video": [
"130",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"115": {
"class_type": "ResolutionSelector",
"inputs": {
"aspect_ratio": "16:9 (Widescreen)",
"megapixels": 0.4,
"multiple": 32
},
"_meta": {
"title": "Resolution Selector (Size)"
}
},
"119": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "minimax_h3_video_vae_fp16.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"120": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "minimax_h3_audio_vae_fp32.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"121": {
"class_type": "VAEDecodeAudio",
"inputs": {
"samples": [
"125",
0
],
"vae": [
"120",
0
]
},
"_meta": {
"title": "VAE Decode Audio"
}
},
"122": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"125",
0
],
"vae": [
"119",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"123": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "res_multistep"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"124": {
"class_type": "BasicScheduler",
"inputs": {
"denoise": 1,
"model": [
"127",
0
],
"scheduler": "simple",
"steps": [
"142",
0
]
},
"_meta": {
"title": "BasicScheduler"
}
},
"125": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"126",
0
],
"latent_image": [
"136",
1
],
"noise": [
"129",
0
],
"sampler": [
"123",
0
],
"sigmas": [
"124",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"126": {
"class_type": "BasicGuider",
"inputs": {
"conditioning": [
"169",
0
],
"model": [
"141",
0
]
},
"_meta": {
"title": "Basic Guider"
}
},
"127": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "minimax_h3_ref2va_pruned_int8_convrot.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"128": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors",
"device": "default",
"type": "minimax"
},
"_meta": {
"title": "Load CLIP"
}
},
"129": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 280970083045691
},
"_meta": {
"title": "RandomNoise"
}
},
"130": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"121",
0
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": 24,
"images": [
"122",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"131": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "max(5, round(a * 24)) + (5 - (max(5, round(a * 24)) % 17)) % 17",
"values.a": [
"132",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"132": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 5
},
"_meta": {
"title": "Float (Duration)"
}
},
"136": {
"class_type": "MiniMaxH3ReferenceToVideo",
"inputs": {
"audio_vae": [
"120",
0
],
"clip": [
"128",
0
],
"height": [
"115",
1
],
"length": [
"131",
1
],
"prompt": [
"138",
0
],
"ref_image_size": "match",
"ref_images.ref_image_0": [
"164",
0
],
"vae": [
"119",
0
],
"width": [
"115",
0
]
},
"_meta": {
"title": "MiniMax H3 Reference to Video"
}
},
"138": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "subject_definitions:\n<Subject 1> is the woman in <Picture 1>, featuring pale skin, bright red lipstick, wearing a white textured swim cap covered in raised bumps and a blue sleeveless collared shirt with white polka dots.\n<Picture 1> is the first frame of [Shot 1], showing <Subject 1> holding a green apple with a leaf over her right eye against a solid blue background.\n<Picture 2> is the keyframe of [Shot 2], showing the woman wearing a smooth teal green swim cap and a red swimsuit top, resting her chin on a red ball stacked on a soccer ball, while holding a red tennis racket that casts a grid shadow across her face.\n<Picture 3> is the keyframe of [Shot 3], showing the woman in a black geometric textured swim cap and a sleek black swimsuit leaning over a vivid blue table towards a yellow apple with a matchstick stuck in it on a red plate, with a mirror reflecting the arrangement against an ocean background.\n<Picture 4> is the first frame of [Shot 4], showing a blurry, ethereal white humanoid head and neck in profile against a soft blue-gray gradient background.\n\nsummary:\n[keyframe completion + reference generation] The target video is a dynamic fashion photography collection featuring <Subject 1> in various surreal, highly stylized vignettes. It begins with <Picture 1> as <Subject 1> dynamically poses with a green apple against a solid blue background. The video then progresses through rapid stylistic cuts: first matching <Picture 2> where she balances her chin on stacked balls while a racket casts a shifting grid shadow on her face, and then matching <Picture 3> where she leans over a table towards a yellow apple with a matchstick, set against a rippling ocean backdrop. The video concludes by cutting to the abstract, blurry white humanoid profile from <Picture 4>, which slightly vibrates before freezing to end the sequence.\n\nretention_analysis:\n<Subject 1> (appears in [Shot 1], [Shot 2], [Shot 3]): partially_preserved - <Subject 1>'s facial identity, pale skin, and distinct red lipstick are maintained across the first three shots, but her swim cap and clothing are explicitly changed in [Shot 2] and [Shot 3] to match the distinct fashion styles of those keyframes.\n<Picture 1> ([Shot 1] first frame): fully_preserved - the video starts exactly from <Picture 1>'s framing, subject state, and solid blue background.\n<Picture 2> ([Shot 2] keyframe): fully_preserved - the specific surreal arrangement of the red ball, soccer ball, tennis racket, and the resulting grid shadow on the face is accurately recreated in [Shot 2].\n<Picture 3> ([Shot 3] keyframe): fully_preserved - the precise composition of the black-clad model, the yellow apple with a matchstick on a red plate, the mirror reflection, and the outdoor ocean background is accurately established in [Shot 3].\n<Picture 4> ([Shot 4] first frame): fully_preserved - the blurry, abstract white humanoid profile is directly used as the static ending composition of [Shot 4].\n\ndetailed_description:\nThe target video is a dynamic fashion photography film collection presented in a highly stylized, cinematic live-action medium. The visuals are characterized by bold, contrasting primary colors, crisp lighting, and surreal, editorial compositions.\n\n[Shot 1] The shot begins from <Picture 1>. <Subject 1> is positioned centrally against a vibrant, solid blue background. She wears a striking white textured swim cap covered in small raised bumps, complementing her blue sleeveless collared shirt adorned with white polka dots. Her pale skin and bright red lipstick stand out vividly. She holds a bright green apple with a single, crisp green leaf directly over her right eye, gripping it lightly with her slender fingers. To fulfill the dynamic fashion intent, the camera pushes in sharply. As the framing tightens, <Subject 1> slowly lowers the green apple away from her face, revealing her intense, unblinking gaze. The crisp studio lighting highlights the textures of her cap and the smooth surface of the apple, establishing a high-fashion, editorial atmosphere.\n\n[Shot 2] At 00:01.500, the shot cuts to the next fashion vignette, whose keyframe corresponds to <Picture 2>. <Subject 1> is now seen in profile against a two-toned background of solid blue above and a vibrant red surface below. She wears a smooth teal green swim cap and a red swimsuit top. Her pose is sculptural: she rests her chin gracefully atop a small red ball, which is precariously stacked on a classic black-and-white soccer ball. In her hand, she holds a bright red tennis racket vertically near her face. The strong directional sunlight casts a distinct, sharp grid shadow from the racket's strings across her closed eyes and pale skin. The camera executes a smooth, continuous arc shot around her. This movement causes the harsh grid shadow to dynamically glide and warp across her facial contours, while she subtly tilts her head, maintaining her perfectly still, mannequin-like pose amidst the camera motion.\n\n[Shot 3] At 00:03.000, the shot cuts to an outdoor surreal composition, whose keyframe corresponds to <Picture 3>. The setting features a bright blue ocean and a clear sky in the background. <Subject 1>, now wearing a black textured swim cap featuring geometric triangular patterns and a sleek black swimsuit, leans dramatically forward over a vivid blue table. In front of her, a glossy red plate holds a perfectly smooth yellow apple, which has a single unlit matchstick pierced upright into its top. A round vanity mirror on a silver stand sits just behind the plate, perfectly reflecting the back of the apple, the matchstick, and a sliver of the ocean. The camera tracks slowly to the right as <Subject 1> continues to lean closer to the apple, her lips slightly parted. The natural sunlight creates sharp, defined shadows on the blue table, while the ocean waves in the background gently ripple and shift, adding environmental dynamism to the editorial shot.\n\n[Shot 4] At 00:05.000, the shot cuts to the concluding sequence, anchored by <Picture 4>. The scene shifts abruptly to a highly abstract, ethereal presentation. A heavily blurred, glowing white humanoid head and neck in profile are silhouetted against a soft blue-gray gradient background. The figure appears ghost-like, devoid of distinct facial features. The camera holds a static frame as the white silhouette exhibits a subtle, vibrating motion, its edges smearing gently into the blue background. After this brief, haunting movement, the figure completely freezes in place, providing a stark, arresting final image that concludes the dynamic fashion showcase.\n\noverall_soundscape:\nThe video features a stylized, rhythmic soundscape with subtle, crisp Foley effects like fabric swishes, ocean ripples, and gentle air movements synchronized to the camera motions, enhancing the high-end editorial aesthetic.\n\nnon_diegetic_music:\nA punchy, dynamic electronic beat with a fast tempo, ticking hi-hats, and heavy bass serves as the driving soundtrack, matching the high-energy, rapid-fire cuts of the fashion vignettes."
},
"_meta": {
"title": "Input Text (Prompt)"
}
},
"141": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"127",
0
],
"on_true": [
"145",
0
],
"switch": [
"146",
0
]
},
"_meta": {
"title": "If/Else Switch (model)"
}
},
"142": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"143",
0
],
"on_true": [
"144",
0
],
"switch": [
"146",
0
]
},
"_meta": {
"title": "If/Else Switch (Steps)"
}
},
"143": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 20
},
"_meta": {
"title": "Int (Full)"
}
},
"144": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 4
},
"_meta": {
"title": "Int (Lightning LoRA)"
}
},
"145": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "minimax_h3_ref2v_turbo_4step_v0.1_comfyui_bf16.safetensors",
"model": [
"127",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
},
"146": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": False
},
"_meta": {
"title": "Boolean (Enable Lightning LoRA)"
}
},
"147": {
"class_type": "MiniMaxH3AddGuide",
"inputs": {
"audio_vae": [
"120",
0
],
"frame_idx": [
"153",
1
],
"image": [
"157",
0
],
"latent": [
"136",
1
],
"positive": [
"136",
0
],
"vae": [
"119",
0
]
},
"_meta": {
"title": "Add Guide for MiniMax H3"
}
},
"153": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "round (a * 24)",
"values.a": [
"154",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"154": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 1.5
},
"_meta": {
"title": "Frame Index (Second)"
}
},
"157": {
"class_type": "LoadImage",
"inputs": {
"image": "h3_frame_ref_2.png"
},
"_meta": {
"title": "Load Image"
}
},
"159": {
"class_type": "LoadImage",
"inputs": {
"image": "h3_frame_ref_3.png"
},
"_meta": {
"title": "Load Image"
}
},
"160": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 3
},
"_meta": {
"title": "Frame Index (Second)"
}
},
"161": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "round (a * 24)",
"values.a": [
"160",
0
]
},
"_meta": {
"title": "Math Expression"
}
},
"162": {
"class_type": "MiniMaxH3AddGuide",
"inputs": {
"audio_vae": [
"120",
0
],
"frame_idx": [
"161",
1
],
"image": [
"159",
0
],
"latent": [
"136",
1
],
"positive": [
"147",
0
],
"vae": [
"119",
0
]
},
"_meta": {
"title": "Add Guide for MiniMax H3"
}
},
"164": {
"class_type": "LoadImage",
"inputs": {
"image": "h3_frame_ref_1.png"
},
"_meta": {
"title": "Load Image"
}
},
"167": {
"class_type": "LoadImage",
"inputs": {
"image": "h3_frame_ref_4.png"
},
"_meta": {
"title": "Load Image"
}
},
"168": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 5
},
"_meta": {
"title": "Frame Index (Second)"
}
},
"169": {
"class_type": "MiniMaxH3AddGuide",
"inputs": {
"audio_vae": [
"120",
0
],
"frame_idx": [
"170",
1
],
"image": [
"167",
0
],
"latent": [
"136",
1
],
"positive": [
"162",
0
],
"vae": [
"119",
0
]
},
"_meta": {
"title": "Add Guide for MiniMax H3"
}
},
"170": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "round (a * 24)",
"values.a": [
"168",
0
]
},
"_meta": {
"title": "Math Expression"
}
}
})
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)Questions & answers
Each reference input on MiniMaxH3ReferenceToVideo has a timestamp and strength. Set the timestamp to your target moment (check your node’s label—some builds expect seconds, others a frame index). If it expects frames, multiply seconds by FPS. Strength controls how strongly the frame is enforced at and around that moment.
The workflow decodes native stereo audio from H3 via VAEDecodeAudio and muxes it in CreateVideo. To mute, disconnect or toggle off the audio path with ComfySwitchNode before CreateVideo. To replace, route your own audio source into CreateVideo’s audio input instead of the decoded track.
Use the ResolutionSelector presets to keep dimensions divisible by 32 and balanced for speed/quality. Good 16:9 options include 736×416 (~0.3MP) and 960×544 (~0.5MP). For custom sizes, ensure width and height are multiples of 32 to avoid decode artifacts.
Increase the anchor’s strength, place an additional anchor later in the timeline, or move the anchor slightly earlier. Also ensure your references match the intended aspect ratio, lighting, and camera angle. If everything is too locked, reduce strengths so the model can transition smoothly between anchors.