H3 Audio Drive Long (any length)
27 seconds of dialogue, six windows, one honest catch
- model
- clip
- video_vae
- audio_vae
- audio
- first_frame
- ref_image
- frames
- audio
- frames_total
- report
One node instead of a graph you can't build
H3 generates 4–15 second clips, full stop. Anything longer is windows: sample a chunk, take its last frame, feed that into the next chunk, stitch. In a normal ComfyUI graph that's a cycle - latent → sample → decode → next first_frame → sample - and you can't express a cycle in a DAG.
So H3AudioDriveLong chews the loop internally. Give it the H3 loaders, a prompt, an audio file of any length, and it plans grid-legal windows, freezes the matching slice of your track into each window's AV latent, samples that window with its own guider and sigma schedule, decodes it, carries the last frame forward, concatenates the lot, and hands back a track that's exactly as long as the frames it produced. One node, four outputs, no subgraph bookkeeping.
Measured on a 27.19 s MP3 at 864×480 / 12 steps: 6 windows, 659 frames (27.458 s), about 13 minutes on a 3090 Ti. Cost scales linearly, as you'd expect.
The catch, stated plainly
This is the part the README is refreshingly honest about, and it's the thing to know before you plan a five-minute talking-head short.
When a window carries an image anchor, H3 switches to image-to-video semantics and largely stops listening to the audio half of the latent. So:
chain_frames=True(the stable choice): the subject stays the same person, the pose is continuous, and window 2 onward scores 0.00 against its own audio. It does score ~0.40 against window 1's audio - it's still performing the previous take's rhythm, just not the new slice.chain_frames=False: window 2 tracks its audio properly (0.55 in the same measurement) and the subject walks off into being a different person at the seam.chain_frames=Falseplus aref_image: same person, but the take goes static.
Null controls on the same frames - shuffled audio 0.08, white noise 0.01, an unrelated speaker −0.09 - tell you that 0.00 is a real absence, not a flat measurement.
Which leaves you with: a stable subject or tracking lips across a seam, not both. Not with this model, today. The honest recipes are chain plus a post-hoc lip-sync pass on the result (the pack's Wav2Lip node, or H3LipSyncTransfer onto the stable face), or unchain and cut between windows like an editor would. If you find that disappointing, you're not alone - it's the reason this pack has five nodes instead of one.
Inputs worth setting
The loaders are the usual H3 four: model, clip, video_vae, audio_vae, plus audio and prompt. Then:
max_window_seconds defaults to 5 and gets snapped down onto the 17k+5 grid. Five seconds keeps VRAM flat and seams predictable; 5.0 s becomes 124 frames.
max_windows at 0 means automatic - as many windows as the audio needs. A positive value is a safety cap, and it's the good kind of cap: it refuses with the exact count you need rather than quietly truncating your track. 27.19s of audio needs 6 windows of 5.17s, but max_windows=4 only covers 20.67s is a much better error message than a half-rendered take.
chain_frames is the decision above. seam_fade_frames cross-fades around the seam if you want it, though with chaining on, the seam is usually invisible and 0 is fine. steps (12), sampler_name, scheduler, seed are your sampling controls. audio_offset_frames shifts the returned track - mux only, length preserved - because H3 plays the mouth a consistent ~10 frames ahead of the audio.
Optional inputs: first_frame anchors window 1 at frame zero, and ref_image gives the text encoder an identity reference (it sees it as <Picture 1>) without an actual frame anchor, so window 1 stays audio-driven.
Outputs: frames into VHS_VideoCombine or CreateVideo, audio into the same node's audio input (already length-matched, so the mux can't drift), frames_total as an integer, and report - read it, it prints the window plan and the measured-limits reminder.
Install
Manager → H3 Audio Drive Auto, or:
cd ComfyUI/custom_nodes
git clone https://github.com/lebao-arch/comfyui-h3-audio-drive-auto
pip install soundfile # the pack imports it at load time but doesn't declare it
Restart, and make sure all four H3 model files are in place - this node needs the video VAE and audio VAE, and it fails informatively-but-annoyingly if either is missing. No external tools, no second venv; everything here runs in ComfyUI's own process.
Troubleshooting
It refused before sampling, complaining about frame memory. That's the roughly 16 GB budget guard for collected frames. It tells you the chunk length to render separately - the message is the fix.
Window 2 scores 0.00. If chain_frames is on, that's the model behaving as documented, not a bug in your wiring. Score window 1 separately to confirm the graph is right, then decide which recipe you're on.
Everything scores well on a music bed. The scorer correlates picture motion with loudness. A good score on non-speech audio proves the mouth moves with the beat, not that it forms words.
The audio is longer than the picture. Expected - the node pads or trims to frame count and says so in report. Trust the returned track, not your source file.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | MiniMax H3 diffusion model (a patched/EasyCache model is fine). | |
| clip | CLIP | The MiniMax H3 text encoder (CLIPLoader type=minimax). | |
| video_vae | VAE | minimax_h3_video_vae_fp16. | |
| audio_vae | VAE | minimax_h3_audio_vae_fp32. | |
| audio | AUDIO | Drives every window. The same waveform is returned for the mux. | |
| prompt | STRING | — | |
| width | INT | 86464–4096 | — |
| height | INT | 48064–4096 | — |
| max_window_seconds | FLOAT | 5.001–15 | Window length. H3 was trained around 5-15 s; 5 s keeps VRAM flat and seams predictable. |
| steps | INT | 121–100 | — |
| sampler_name | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduler | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| seed | INT | 420–18446744073709550000 | — |
| seam_fade_frames | INT | 00–12 | 0 = hard cut (the new window is generated from the previous last frame, so the seam is normally invisible). >0 cross-fades that many frames around the seam. |
| chain_frames | BOOLEAN | false | Anchor each window on the previous last frame. Keeps the subject stable across seams, but an image anchor makes H3 treat window 2+ as image-to-video and they stop following their own audio (measured 0.00 vs 0.55 unchained). Off = lips track, subject may walk away from you. |
| max_windows | INT | 00–200 | 0 = automatic: use as many windows as the audio needs. A positive value is a safety cap; the node refuses (with the exact window count you need) instead of silently truncating your audio. |
| audio_offset_frames | INT | 0-48–48 | Shift the RETURNED audio against the rendered frames, in frames at 24 fps (length preserved). H3 plays the mouth ~10 frames ahead of the track, so -10 lands them on the same frame; use the offset H3LipSyncScore reports. The conditioning audio is never shifted. |
| first_frameopt | IMAGE | Anchors window 1 at frame 0. | |
| ref_imageopt | IMAGE | Identity reference seen by the text encoder as <Picture 1> (or <Picture 2> when first_frame is also connected). No frame anchor, so window 1 stays audio-driven - but window 2+ still stop tracking their own audio when this is connected (measured 0.00). |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| frames | IMAGE | — |
| audio | AUDIO | — |
| frames_total | INT | — |
| report | STRING | — |