Skip to content

feat(minimax-h3): invocations, denoise loop, and audio-video decode (PR 3/5) - #140

Open
lstein wants to merge 1 commit into
minimax-h3/02-model-supportfrom
minimax-h3/03-nodes
Open

feat(minimax-h3): invocations, denoise loop, and audio-video decode (PR 3/5)#140
lstein wants to merge 1 commit into
minimax-h3/02-model-supportfrom
minimax-h3/03-nodes

Conversation

@lstein

@lstein lstein commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

PR 3 of the MiniMax H3 stack (on top of #139): the six generation nodes, the packed-row denoise loop, and audio+video decode. With this PR a hand-built graph in the Workflow Editor produces a playable MP4 with an AAC stereo soundtrack — no linear UI yet (that's PR 4).

Backend modules (invokeai/backend/minimax_h3/)

  • packing.py — vendored from diffusers PR #14355 @ abc5e9bf71 (packed-sequence geometry + checkpoint constants; byte-identical apart from import rewrites).
  • sampling.py — denoise-state construction: packed layout (condition rows lead), two MiniMaxH3Schedulers (video shift 12.0 / audio shift 3.0), one generator with the upstream draw order (keyframe → video → audio), frame-grid validation (num_frames % 17 == 5, 5–15 s window, plus exactly 5 frames as the still-image mode).
  • denoise.py — the joint audio-video loop: one forward per step (guidance-distilled, no CFG), per-row timestep plans, keyframe rows pinned at t=0.999, condition rows never stepped.
  • text_conditioning.py — Qwen3-VL-32B prompt encoding (unnormalized layer-50 hidden states; keyframes enter the vision context via the processor).
  • keyframe_conditioning.py — keyframe VAE encoding (seed-42 posterior sample, fp16 rounding contract, stretch/cover canvas placement in packed order).

Nodes (all Prototype)

minimax_h3_model_loader, minimax_h3_text_encoder (idle-GPU-offloadable), minimax_h3_frame_conditioning, minimax_h3_denoise, minimax_h3_latents_to_video (video VAE decode + audio VAE decode → WAV → AAC mux via PR 1's make_mp4_writer), minimax_h3_latents_to_image (single-frame extraction = txt2img path).

Plus plumbing: MiniMaxH3ConditioningInfo (+ serializer safe-globals), fields/primitives/metadata generation modes, grayscale 24-channel latent preview fallback, H3 VAE working-memory estimator.

Deliberate divergences from upstream

  • Non-grid num_frames values are rejected, not rounded (InvokeAI validator convention). Effective max is 345 frames = 14.375 s.
  • Exactly 5 frames is allowed as a still-image mode (upstream enforces 5–15 s always).
  • fp16-autocast decode (upstream's verified recipe) is used on CUDA only; ROCm/MPS/CPU decode in the weights' dtype.
  • Latent previews are grayscale until RGB factors are calibrated against real weights (TODO noted in step_callback.py).

Adversarial review fixes (already in)

  • The decode node no longer toggles enable_tiling()/disable_tiling() on the shared cached VAE — the H3 VAE tiles by default and the released frames are the blended-tile ones; toggling would have silently changed every later encode/decode of the cached instance.
  • The VAE working-memory estimator now models the always-tiled decode (per-tile working set + on-device output clip) instead of a full-frame decode that never happens; the decoded clip moves to the CPU before the full-clip pixel math.
  • The denoise node cross-checks keyframe coupling: the prompt's vision-context keyframes (anchors + canvas, now carried on MiniMaxH3ConditioningInfo) must match the frame-conditioning input.
  • steps is ge=2 (the scheduler's contract; N grid points = N−1 model evaluations).
  • Audio is zero-padded as well as trimmed to the exact video duration; temp-WAV cleanup on write failure.

Testing

  • tests/backend/minimax_h3/: grid math, draw-order determinism, full denoise loop on a micro-config CPU transformer (anchor preservation, cancellation, callback counts).
  • Full sweep tests/app + tests/backend: 2871 passed / 0 failures; post-review-fix sweep of tests/backend + tests/app/util: 1712 passed.
  • ruff clean, pnpm lint:tsc green, openapi.json/schema.ts regenerated.
  • Real-weights end-to-end (playable MP4 with audible audio) still needs a manual run — that's this PR's test gate.

🤖 Generated with Claude Code

Third PR of the MiniMax H3 stack: the six Prototype nodes and the
first-party port of the FL2VA sampling machinery.

Vendored (byte-faithful, imports rewritten): packing.py — the packed
[text | keyframe conditions | audio | video] sequence geometry and the
checkpoint constants (fp64 rotary grid, 17n+5 frame grid, keyframe
noise-aug 0.999, posterior seed 42).

First-party backend ports (from the diffusers modular blocks at the
vendored commit):
- sampling.py: denoise-state construction — one CPU-seeded generator,
  three draws in upstream order (keyframe -> video -> audio), two
  MiniMaxH3Schedulers (video shift 12.0, audio shift 3.0), per-step
  row-timestep plan with condition rows pinned at t=0.999.
- denoise.py: one transformer forward per step over the packed rows;
  per-modality scheduler steps on generated rows only (anchors survive
  by construction); guidance-distilled, no CFG; InvokeAI cancellation
  and step-callback hooks.
- text_conditioning.py: Qwen3-VL layer-50 unnormalized hidden state,
  "<Picture i>: " + vision-block keyframe presentation, LM head never
  runs.
- keyframe_conditioning.py: spatial-only VAE encode, fp16 rounding
  before normalization, fixed seed-42 posterior sample.

Nodes: model loader (6 submodels), text encoder (idle-GPU-offloadable,
optional keyframe vision context), frame conditioning (clean rows;
denoise node noise-augments them), denoise (joint video+audio latents
out), latents-to-video (VAE decode + AAC stereo mux, tiled fallback,
duration-trimmed WAV), latents-to-image (still/frame extraction).

Plumbing: MiniMaxH3ConditioningInfo (embeds + text token tags travel
together), serializer safe-globals, generation modes, grayscale
latent-preview fallback (24ch/16x), H3 VAE working-memory estimator.

Tests: packed-grid math, frame-count validation (5..345 window plus
5-frame still path), noise determinism and draw-order shifts, and the
full loop on a micro-config CPU transformer (shapes, anchor
preservation, callback count, cancellation, determinism). Full
tests/app + tests/backend sweep green (2871 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant