Co-authored-by: SolitaryThinker <wlsaidhi@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MMAudio dataset inference and evaluation
This example evaluates a trained MMAudio checkpoint without importing the
upstream MMAudio package. Generation uses FastVideo's native
MMAudioPipeline; the default metrics use fastvideo.eval.
Relation to official MMAudio
Official batch_eval.py launches one complete model replica per GPU with
torchrun, uses a DistributedSampler, runs batched bf16 inference, and
writes audio without composing videos. Metric calculation is a separate step
through av_bench.extract and av_bench.evaluate.
This FastVideo path keeps that high-level separation:
- one complete MMAudio pipeline replica per GPU;
- data-parallel dataset inference to WAV;
- a canonical JSONL manifest that binds id, source video, generated audio, caption, seed, and reference-audio source;
- independent multi-GPU metric workers over the complete corpus.
There are two intentional differences. Rank-strided indices avoid the padded
duplicates that PyTorch DistributedSampler(drop_last=False) can introduce,
and cached CLIP/Synchformer/text features skip video decoding and conditioning
encoder work already completed during FastVideo preprocessing. The current
cached-feature stage accepts one sample per pipeline call; four GPUs still
process four samples concurrently.
Environment
Use the same FastVideo environment as training:
cd /mnt/lustre/vlm-kai/FastVideo
source .venv/bin/activate
uv pip install --python .venv/bin/python hear21passt pyloudnorm
The four default native metrics are:
| FastVideo metric | Protocol |
|---|---|
audio.frechet_distance |
corpus PaSST FAD / FD_PaSST |
audio.kl_divergence |
paired PaSST KL, `KL(gt |
audio.clap_score |
text-audio CLAP similarity |
audio.desync |
source-video/generated-audio Synchformer DeSync |
FAD and KL port the av-benchmark mathematics. DeSync vendors the same Synchformer family. FastVideo CLAP uses the Hugging Face LAION CLAP checkpoint and is not byte-identical to the external package's CLAP implementation; use the optional official backend below when exact paper-table reproduction is required.
1. Export the final EMA
The training result is a transformer state dict. Inference also needs the frozen audio VAE, vocoder, scheduler, and (for raw-video inference) the frozen conditioning encoders. Export a complete FastVideo model once:
bash examples/inference/eval/mmaudio/export_final_ema.sh
Default input:
outputs/mmaudio_small_44k_ddp_from_scratch/posthoc_ema/official_ddp/
mmaudio_ema_final_sigma_0p05_step_000300000.pth
Default output:
converted_weights/mmaudio/small_44k_ema_300000/
Override EMA_CHECKPOINT, OUTPUT_MODEL, or ASSET_ROOT before the command
for another run or variant.
2. Multi-GPU inference
The launcher defaults to the VGGSound test feature cache and four GPUs:
bash examples/inference/eval/mmaudio/run_inference_vggsound.sh
For a four-sample smoke test:
MAX_SAMPLES=4 \
OUTPUT_DIR=outputs/mmaudio_small_44k_ema_300000_vggsound_smoke \
bash examples/inference/eval/mmaudio/run_inference_vggsound.sh
For a background full run with a persistent log:
mkdir -p logs
nohup bash examples/inference/eval/mmaudio/run_inference_vggsound.sh \
> logs/mmaudio_vggsound_inference.log 2>&1 &
tail -f logs/mmaudio_vggsound_inference.log
The output directory contains:
audio/<sample-id>.wav
eval_manifest.jsonl
failures.jsonl
summary.json
manifest_rank_*.jsonl
failures_rank_*.jsonl
Existing WAV files are resumed rather than regenerated. Add --overwrite to
the Python runner when intentional regeneration is required. Seeds are
base_seed + global_index, so results do not change with GPU count.
3. Native FastVideo evaluation
Run FAD, KL, CLAP, and DeSync with four metric replicas:
bash examples/inference/eval/mmaudio/run_evaluate_vggsound.sh
The first run extracts ground-truth audio from each source MP4 into
<OUTPUT_DIR>/reference_audio and caches metric weights. Later runs reuse
both. Results are written to fastvideo_eval_results.json; per-sample metrics
are under samples, while FAD is under corpus.
The underlying generic command is:
fastvideo eval run \
--manifest outputs/mmaudio_small_44k_ema_300000_vggsound_test/eval_manifest.jsonl \
--metrics audio.frechet_distance,audio.kl_divergence,audio.clap_score,audio.desync \
--num-gpus 4 \
--extract-audio outputs/mmaudio_small_44k_ema_300000_vggsound_test/reference_audio \
--extract-workers 16 \
--output-format full \
--output outputs/mmaudio_small_44k_ema_300000_vggsound_test/fastvideo_eval_results.json
Do not evaluate FAD by invoking the evaluator once per file. FAD is a
set-vs-set statistic; this CLI submits the complete manifest in one call and
serializes EvalResults.corpus.
Exact external av-benchmark backend
For strict comparison to official MMAudio numbers, FastVideo provides the
dedicated fastvideo eval v2a command. It launches the exact
av_bench.extract and av_bench.evaluate functions with a Python interpreter
from an isolated environment. This keeps av-benchmark's CLAP, ImageBind, and
PyTorch dependencies out of the main FastVideo environment.
Create the isolated environment once:
cd /mnt/lustre/vlm-kai
git clone https://github.com/hkchengrex/av-benchmark.git
uv venv av-benchmark/.venv --python 3.12
uv pip install --python av-benchmark/.venv/bin/python -e av-benchmark
# PyTorch 2.9+ routes torchaudio decoding through TorchCodec. Transformers 5
# removed an API used by the vendored Synchformer AST, while SciPy 1.17 removed
# an argument used by the official FAD implementation. Keep these constraints
# in this isolated environment; select the wheel matching its PyTorch CUDA build.
UV_TORCH_BACKEND=cu130 uv pip install \
--python av-benchmark/.venv/bin/python \
torchcodec==0.15.0 'transformers<5' 'scipy<1.17'
mkdir -p av-benchmark/weights
curl -L https://huggingface.co/lukewys/laion_clap/resolve/main/music_speech_audioset_epoch_15_esc_89.98.pt \
-o av-benchmark/weights/music_speech_audioset_epoch_15_esc_89.98.pt
curl -L https://github.com/hkchengrex/MMAudio/releases/download/v0.1/synchformer_state_dict.pth \
-o av-benchmark/weights/synchformer_state_dict.pth
Download only the official VGGSound ground-truth cache (about 16 GB):
cd /mnt/lustre/vlm-kai/FastVideo
.venv/bin/hf download hkchengrex/MMAudio-precomputed-results \
--repo-type dataset \
--include "vggsound-test-eval-cache/*" \
--local-dir /mnt/lustre/vlm-kai/datasets/VGGSound/av_benchmark
Then run the dedicated launcher:
bash examples/inference/eval/mmaudio/run_evaluate_vggsound_av_benchmark.sh
For a background run:
nohup bash examples/inference/eval/mmaudio/run_evaluate_vggsound_av_benchmark.sh \
> logs/mmaudio_vggsound_av_benchmark.log 2>&1 &
tail -f logs/mmaudio_vggsound_av_benchmark.log
The official VGGSound cache produces the complete paper-style metric set:
FD-VGG, FD-PANN, FD-PASST
KL-PANNS-softmax, KL-PASST-softmax
ISC-PANNS-mean/std, ISC-PASST-mean/std
IB-Score, DeSync
The official VGGSound cache does not contain CLAP text features, so the launcher
defaults to SKIP_CLAP=1; this saves prediction feature passes without changing
the metric set. Set SKIP_CLAP=0 for a custom GT cache that includes CLAP text
features. Prediction features are cached and reused; set RECOMPUTE=1 to force
a clean extraction.
The launcher also defaults to ALIGN_PREDICTION_KEYS=1. The official
VGGSound cache prepends underscores to some sanitized ids; FastVideo keeps the
original ids. The backend changes only unique matches in prediction feature
caches, leaves WAV filenames untouched, and records exact/remapped/ambiguous/
unmatched counts under prediction_key_alignment in the result JSON.
The launcher defaults to NUM_WORKERS=0: this avoids both the machine's 64 MB
/dev/shm limit and forking workers after the official extractor initializes
CUDA. Raise it only after validating the container and backend combination.
Evaluation protocol warning
The current FastVideo test cache contains the filtered natural-language
descriptions used in this training run. Official MMAudio's VGGSound
batch_eval.py reads class-label captions from the original VGGSound CSV.
FAD, KL, and DeSync formulas do not read captions directly, but changing the
generation caption changes the generated waveform and can therefore change all
scores. CLAP additionally consumes the caption during evaluation. Record the
generation manifest, test split, and ground-truth cache with reported results.