Zhengming Yu1,2,
Junkun Yuan2,
Haotian Yang2,
Gordon Guocheng Qian2,
Yizhi Wang2,
Angtian Wang2,
Yiding Yang2,
Bo Liu2,
Xin Li1,
Wenping Wang1,
Chongyang Ma2
1Texas A&M University, 2ByteDance
This repository contains the 4-step DMAD students of MiniMax-H3 (33B, text-to-audio-video) and the code to run them: a LoRA of rank 128 on the H3 transformer turns the 50-step teacher into a 4-step generator of 1344x768 video with native stereo audio.
Distribution Matching Distillation (DMD) trains a few-step student on the difference between target and student scores, so it must keep an auxiliary diffusion model fitted to the student's evolving distribution at extra memory and computation cost. We introduce DMAD, Distribution Matching as Adversarial Distillation, which recasts distribution matching as classification and learns the required log-density ratios directly. Two discriminator heads on a shared backbone distinguish real data and teacher samples from the student's, and linear losses on their logits train the student without auxiliary score fitting. We prove that at the discriminator optimum these losses recover the distribution-matching gradient underlying DMD, through the classical identity linking discriminator logits to log-density ratios. We further introduce gap-based reweighting, which adapts teacher supervision across noise levels from the real-data head's empirical logit gap between real and teacher samples. DMAD reaches a Fréchet Inception Distance (FID) of 1.04 with one-step generation on ImageNet-64x64, 14.47 with four-step SDXL on COCO-10K, and a VBench total score of 85.15 with four-step Wan2.1-T2V-14B, the best values among the compared few-step methods and the multi-step teachers. On MiniMax-H3-33B, our four-step student achieves overall human preference rates of 79.1% over DMD2 and 84.6% over rCM for joint audio-video generation, excluding ties.
This repository contains:
- 🪐 Two DMAD student LoRAs (rank 128, 1.4 GB each):
lora_critic(the checkpoint of the paper) andfull_critic(a full-critic variant that scores higher on AVGen-Bench) - ⚡️
inference.py: few-step sampling with the re-noise step rule the students were trained with (the sampler of all results in the paper), on one 80 GB GPU - 🧩
run_diffusers_pipeline.py: the students inside the official DiffusersMiniMaxH3ModularPipeline
conda create -n dmad_h3 python=3.12 -y
conda activate dmad_h3
# PyTorch (CUDA 12.6)
pip install torch==2.11.0 torchvision==0.26.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cu126
# Diffusers at the commit that carries the MiniMax-H3 classes, plus the rest
pip install -r requirements.txtThe students are LoRAs on MiniMax-H3's text-to-audio-video transformer (the transformer/ partition of the
Diffusers layout). Accept the MiniMax H3 Community License
on Hugging Face, then download the components we need (about 170 GB; the first-/last-frame, omni-reference and
reference-transformer partitions are not needed):
hf download MiniMaxAI/MiniMax-H3 --local-dir models/MiniMax-H3 \
--exclude "FL2VA/*" --exclude "Ref2VA/*" --exclude "transformer_ref/*"Expected layout:
models/MiniMax-H3/
├── model_index.json, modular_model_index.json
├── transformer/ # 33B DiT (14 safetensors shards, bf16)
├── text_encoder/ # Qwen3-VL-32B conditioner
├── tokenizer/, processor/
├── vae/, audio_vae/
└── scheduler/, audio_scheduler/
mkdir -p ckpt
hf download ZhengmingYu/DMAD --include "minimax_h3/*" --local-dir ckpt| File | Checkpoint | Size |
|---|---|---|
minimax_h3/dmad_minimax_h3_4step_lora_critic.safetensors |
the checkpoint of the paper: EMA of the student at iteration 800 of the main run | 1.4 GB |
minimax_h3/dmad_minimax_h3_4step_full_critic.safetensors |
the student of a run whose critic backbone is fully trained (the paper's run keeps it frozen under a LoRA): iteration 1600, live weights; it scores higher on AVGen-Bench | 1.4 GB |
Both are rank-128 LoRAs (alpha 128) on the attention projections and the two feed-forward layers of all 50
transformer blocks and the 2 token-refiner blocks, in the Diffusers key layout (<module>.lora.down.weight,
<module>.lora.up.weight). The safetensors metadata records the rank, alpha and fusion rule.
Everything is text-to-audio-video with 4 steps, time shift 12 for video and 2 for audio, no classifier-free guidance (MiniMax-H3 is guidance-distilled). The default output is 1344x768, 124 frames (5.2 s at 24 fps) with 32 kHz stereo audio, the setting the students were trained at.
# the prompt of assets/dmad_sweater_seed42.mp4: an anime girl in a "DMAD" sweater making a heart gesture, with a
# piano tune; with the lora_critic checkpoint and seed 42 this reproduces that video
python inference.py \
--model-dir models/MiniMax-H3 \
--lora ckpt/minimax_h3/dmad_minimax_h3_4step_lora_critic.safetensors \
--prompt-file prompts/dmad_sweater.txt --seed 42 \
--output-dir outputs/dmad_sweater
# the other checkpoint; a prompt can also be given inline, and a prompt file holds one prompt per line
# (or a .jsonl with {"prompt": ...} per line)
python inference.py --model-dir models/MiniMax-H3 --lora ckpt/minimax_h3/dmad_minimax_h3_4step_full_critic.safetensors \
--prompt-file prompts/dmad_sweater.txt --seed 42 --output-dir outputs/dmad_sweater_full_critic
python inference.py --model-dir models/MiniMax-H3 --lora ckpt/minimax_h3/dmad_minimax_h3_4step_lora_critic.safetensors \
--prompt "A polar bear is playing the violin in the snow." --output-dir outputs/polar_bearPrompt i is written to outputs/<dir>/<i:04d>.mp4 (H.264 + AAC) next to its text, and settings.json records the
arguments. The three models are loaded one after another (text encoder, transformer, VAEs), so the peak is the
transformer stage.
| Option | Default | Notes |
|---|---|---|
--steps |
4 | model evaluations; the students were trained for 4 |
--video-shift, --audio-shift |
12, 2 | time shifts of the sigma grid |
--seed |
42 | one CPU generator draws the video noise, then the audio noise, then the re-noise draws |
--euler |
off | Euler step rule (the official H3 pipeline's) instead of the re-noise rule; the paper's videos use the re-noise rule |
--height, --width |
768, 1344 | multiples of 32 |
--num-frames |
124 | must be 17 * n + 5; the students were trained at 124 |
--offload |
off | stream the transformer to the GPU one block at a time (see Hardware) |
Prompts. MiniMax-H3 was trained on long, structured descriptions (an integrated_multimodal_description: shot
list, overall_soundscape:, non_diegetic_music:); detailed prompts like prompts/dmad_sweater.txt work best, short
ones work too. The prompt is encoded verbatim, with no template, as in the official pipeline.
For users of the official MiniMaxH3ModularPipeline:
python run_diffusers_pipeline.py --model-dir models/MiniMax-H3 \
--lora ckpt/minimax_h3/dmad_minimax_h3_4step_lora_critic.safetensors \
--prompt-file prompts/dmad_sweater.txt --seed 42 --output-dir outputs/diffusersor, in your own code, attach the LoRA to the transformer and set the student's schedule (components are offloaded to the CPU while idle, so one 80 GB GPU is enough):
import torch
from diffusers import ComponentsManager, ModularPipeline
from dmad_h3 import attach_lora, load_transformer, read_lora_file
from dmad_h3.lora import lora_rank_alpha
manager = ComponentsManager()
pipe = ModularPipeline.from_pretrained("models/MiniMax-H3", components_manager=manager)
pairs, meta = read_lora_file("ckpt/minimax_h3/dmad_minimax_h3_4step_lora_critic.safetensors")
transformer = attach_lora(load_transformer("models/MiniMax-H3"), pairs, *lora_rank_alpha(pairs, meta))
pipe.update_components(transformer=transformer.eval())
# the model's modular_model_index.json points at the Hub id, so name the local directory for the other components
pipe.load_components(names=["text_encoder", "tokenizer", "processor", "vae", "audio_vae", "scheduler", "audio_scheduler"],
pretrained_model_name_or_path="models/MiniMax-H3", dtype={"text_encoder": torch.bfloat16})
manager.enable_auto_cpu_offload(device="cuda")
pipe.scheduler.set_shift(12.0)
pipe.audio_scheduler.set_shift(2.0)
prompt = open("prompts/dmad_sweater.txt").read().strip()
result = pipe(prompt=prompt, height=768, width=1344, num_frames=124,
num_inference_steps=5, # 4 model evaluations: the scheduler counts the terminal sigma = 0
generator=torch.Generator().manual_seed(42), output_type="np",
output=["videos", "audio", "sampling_rate"])The pipeline steps with the Euler rule, so its videos differ from inference.py's (whose re-noise rule is what the
students were trained with and what the paper reports). In our evaluation the re-noise rule scores higher.
@misc{yu2026dmad,
title = {DMAD: Distribution Matching as Adversarial Distillation for Fast Visual Generation},
author = {Zhengming Yu and Junkun Yuan and Haotian Yang and Gordon Guocheng Qian and Yizhi Wang and
Angtian Wang and Yiding Yang and Bo Liu and Xin Li and Wenping Wang and Chongyang Ma},
year = {2026},
eprint = {2610.02188},
archivePrefix = {arXiv}
}- MiniMax-H3, the teacher and base model of the students.
- LightX2V, whose training framework our DMAD training code builds on.
- Diffusers, whose MiniMax-H3 implementation runs the transformer, the VAEs and the official pipeline.
Thanks to their authors for the open-source contributions.
The code in this repository is released under the Apache License 2.0.
