Instructions to use FastVideo/FastH3-Omni-MLX with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use FastVideo/FastH3-Omni-MLX with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] hf download FastVideo/FastH3-Omni-MLX --local-dir FastH3-Omni-MLX
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
File size: 19,618 Bytes
0ac7396 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | #!/usr/bin/env bash
# Build the FastH3 Omni MLX benchmark model directory from PUBLIC Hugging Face
# sources. Resumable, idempotent, self-verifying. Run `./prepare_model_dir.sh --help`.
set -euo pipefail
KIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HELPERS="$KIT_DIR/prepare_helpers.py"
# ---- Pinned source revisions (HF `main` commit SHAs fetched 2026-10-20) ------
REV_OMNI="53e0d26a1691aa473b6262d8196a8feb2c297df0" # FastVideo/FastVideo-FastH3-Omni-8-Step-V1
REV_QAD="f01e6a23ac6066aa9eb622cf94b6259442e70ec2" # FastVideo/FastH3-Omni-NVFP4-QAD
REV_DEC="bd0c248f2a0f57ca643b3df2ac1f375fa55101fb" # FastVideo/FastH3-NVFP4-VAE-Decoder
REV_LVAE="4925ea978147b9de492d7a5fd4f9c6d1854ca1cc" # lightx2v/LightVAE
REPO_OMNI="FastVideo/FastVideo-FastH3-Omni-8-Step-V1"
REPO_QAD="FastVideo/FastH3-Omni-NVFP4-QAD"
REPO_DEC="FastVideo/FastH3-NVFP4-VAE-Decoder"
REPO_LVAE="lightx2v/LightVAE"
ENCODER_SOURCE_FIELD="hf://FastVideo/FastH3-Omni-NVFP4-QAD/text_encoder"
# Reference SHA-256 of our build (from the validated model dir). Downloaded/copied
# files must match exactly (failure). dit/* and root/text_encoder/{model.safetensors,
# mlx_h3_nvfp4_encoder.json} are converter outputs: a mismatch is only a WARNING
# (MLX version / hardware may change the quantized bytes).
read -r -d '' EXPECTED_SHA256 <<'EXPECTED_EOF' || true
59b99642b95ea21630e311198ddbfffbfe05aadba0c2f5d884cbdf4efcc90f44 LICENSE
c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 LICENSE-Qwen3-VL
6f63c0101bdd0c7188ba540277ddd619952e2874437f9702bcdfa644b355dbc4 NOTICE
fcc29480ea8247d75b5bdb86805c03044083af614244600d13467814acd4eb9b dit/int6/mlx_h3_dit.json
9ea28f8944686dbfecd684664ea5574b90994e3f232c4552b5c15dfc1faeb446 dit/int6/mlx_h3_dit.safetensors
804780f7133477067bd6bbfbc02dc8b3cf9feeb400f97c08f5b1d5f6cbab3840 root/audio_scheduler/scheduler_config.json
9a3c645ff892b376c6f5f4c8685964cd75474731af594ff058492a0000caabb6 root/audio_vae/config.json
52c59e67ba8de5477c81bfbced0327aabf500f1bfdeefd5ee754529241cb26cb root/audio_vae/diffusion_pytorch_model.safetensors
68577f23f0c866e329aa8a578b2455e4ca9a26a3ca1d15ddd6d0e99091007e18 root/fastvideo_inference.json
5c72a170d2a4a1a3bc5adad2e689ae28138a9700e5b8c96c0266331e86c0acce root/processor/chat_template.json
599bab54075088774b1733fde865d5bd747cbcc7a547c5bc12610e874e26f5e3 root/processor/merges.txt
27225450ac9c6529872ee1924fcb0962ff5634834f817040f444118116f4e516 root/processor/preprocessor_config.json
a5d85b6dcc535e6b93115a9ef287e6132fdbf30270da6218194ba742261173c7 root/processor/tokenizer.json
a07e942ac874baa13758de8d1fbdb186683cc03416b5589e1b6671c6b3057c68 root/processor/tokenizer_config.json
7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13 root/processor/video_preprocessor_config.json
ca10d7e9fb3ed18575dd1e277a2579c16d108e32f27439684afa0e10b1440910 root/processor/vocab.json
8fa6c3aa70dc9e691e1a6df899fd1b6f75f70481a27cee6e18a303817075c304 root/scheduler/scheduler_config.json
29d4a1e1db0e112612bf1e7c457a42ce9fe13fd0c69a0c3a64c1d291325bd9eb root/text_encoder/config.json
1d50c336c0e34645699039d78e7532fe2e7c21b2ed71f98d4252b682d53e075e root/text_encoder/mlx_h3_nvfp4_encoder.json
f91405a223c95ed013267a6274dbee40d832a28cf89184ab86f84214b1882809 root/text_encoder/model.safetensors
599bab54075088774b1733fde865d5bd747cbcc7a547c5bc12610e874e26f5e3 root/tokenizer/merges.txt
a5d85b6dcc535e6b93115a9ef287e6132fdbf30270da6218194ba742261173c7 root/tokenizer/tokenizer.json
a07e942ac874baa13758de8d1fbdb186683cc03416b5589e1b6671c6b3057c68 root/tokenizer/tokenizer_config.json
ca10d7e9fb3ed18575dd1e277a2579c16d108e32f27439684afa0e10b1440910 root/tokenizer/vocab.json
658c1f6278262db3072d9a6f4832c7c49280f91c94a8455414525cd6648de677 root/transformer_ref/config.json
ffa6d5e7a95dc57ae0494a8c0caf588e2c555252c159104d310ffcc450e1c914 root/vae/config.json
c0d0f1beb88f0579d2a9fb249850419dbf3baa05d86ce37d3135c8c8873b4752 vae/fasth3-fast-8L-decoder-nvfp4.safetensors
84a92170f1cf6737f0509f8350cf642832afe3c0c0b1766bf4a0e6e820b62729 vae/fasth3-quality-36L-decoder-nvfp4.safetensors
4b0e5af102da19324c64df40abbd95008d8acb0b9cf76e4704d74c8ac20cefac vae/lightvae-lite-h3-encoder.safetensors
EXPECTED_EOF
# Approximate sizes in GB.
SRC_GB=95; ENC_GB=16; OUT_FIXED_GB=7 # decoders+encoder(vae)+misc
fmt_gb() { case "$1" in int6) echo 17;; int8) echo 20;; bf16) echo 38;; *) echo 0;; esac; }
# ---- Options -----------------------------------------------------------------
FASTVIDEO=""; MODEL_DIR="$PWD/fasth3-omni-mlx-model"; SOURCES=""; FORMATS="int6"
PYTHON="python3"; SKIP_DOWNLOAD=0; KEEP_SOURCES=0; LOCK_DIR=""; DRY_RUN=0
RESERVE_GB=5 # free space that must remain after each big stage
usage() {
cat <<EOF
Usage: $0 --fastvideo <FastVideo checkout> [options]
--fastvideo DIR FastVideo checkout (branch aryan/omniref-mlx-speed). Required.
--model-dir DIR output model directory (default: $MODEL_DIR)
--sources DIR download directory (default: <model-dir>/../fasth3-sources); may be deleted afterwards
--formats "int6" DiT formats, space/comma separated: int6 (default), int8, bf16
--python PATH python of the FastVideo venv (needs mlx, fastvideo); default python3
--skip-download use existing --sources (layout: omni-bf16/ nvfp4-qad/ vae-decoders/ lightvae/)
--keep-sources do not delete downloaded sources after a successful verified build
--reserve-gb N free GB that must remain after each big stage (default $RESERVE_GB)
--lock-dir DIR opt-in: serialize memory-heavy stages via mkdir DIR/gpu.lock
--dry-run print the hf/conversion commands without running them
Safe to interrupt (Ctrl-C) and re-run: finished stages are verified and skipped.
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--fastvideo) FASTVIDEO="$2"; shift 2;;
--model-dir) MODEL_DIR="$2"; shift 2;;
--sources) SOURCES="$2"; shift 2;;
--formats) FORMATS="$2"; shift 2;;
--python) PYTHON="$2"; shift 2;;
--skip-download) SKIP_DOWNLOAD=1; shift;;
--keep-sources) KEEP_SOURCES=1; shift;;
--reserve-gb) RESERVE_GB="$2"; shift 2;;
--lock-dir) LOCK_DIR="$2"; shift 2;;
--dry-run) DRY_RUN=1; shift;;
-h|--help) usage; exit 0;;
*) echo "unknown option: $1" >&2; usage >&2; exit 2;;
esac
done
[[ -n "$FASTVIDEO" ]] || { echo "error: --fastvideo is required" >&2; usage >&2; exit 2; }
FORMATS="${FORMATS//,/ }"
for f in $FORMATS; do [[ "$(fmt_gb "$f")" != 0 ]] || { echo "error: unknown format '$f' (int6|int8|bf16)" >&2; exit 2; }; done
abspath() { case "$1" in /*) echo "${1%/}";; *) echo "$PWD/${1%/}";; esac; }
MODEL_DIR="$(abspath "$MODEL_DIR")"; FASTVIDEO="$(abspath "$FASTVIDEO")"
[[ -n "$SOURCES" ]] || SOURCES="$(dirname "$MODEL_DIR")/fasth3-sources"
SOURCES="$(abspath "$SOURCES")"
S_OMNI="$SOURCES/omni-bf16"; S_QAD="$SOURCES/nvfp4-qad"; S_DEC="$SOURCES/vae-decoders"; S_LVAE="$SOURCES/lightvae"
log() { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; }
warn() { printf '[%s] WARNING: %s\n' "$(date +%H:%M:%S)" "$*" >&2; WARNINGS+=("$*"); }
die() { printf '[%s] ERROR: %s\n' "$(date +%H:%M:%S)" "$*" >&2; exit 1; }
WARNINGS=(); declare -a TIMINGS=()
run() { if [[ $DRY_RUN -eq 1 ]]; then echo " (dry-run) $*"; else "$@"; fi; }
helper() { "$PYTHON" -I "$HELPERS" "$@"; }
timed() { # timed <label> <command...>; records elapsed time, preserves exit status
local label="$1" t0=$SECONDS rc=0; shift
"$@" || rc=$?
TIMINGS+=("$label: $((SECONDS - t0))s"); return $rc
}
# ---- Lock (opt-in) -------------------------------------------------------------
LOCK_HELD=""
lock_release() { if [[ -n "$LOCK_HELD" ]]; then rm -rf "$LOCK_HELD"; LOCK_HELD=""; fi; }
lock_acquire() {
[[ -n "$LOCK_DIR" && $DRY_RUN -eq 0 ]] || return 0
mkdir -p "$LOCK_DIR"
until mkdir "$LOCK_DIR/gpu.lock" 2>/dev/null; do
log "waiting for $LOCK_DIR/gpu.lock (owner pid $(cat "$LOCK_DIR/gpu.lock/owner" 2>/dev/null || echo ?)); retry in 30 s"
sleep 30
done
LOCK_HELD="$LOCK_DIR/gpu.lock"; echo $$ > "$LOCK_HELD/owner"; log "acquired $LOCK_HELD"
}
trap 'lock_release' EXIT
trap 'lock_release; exit 130' INT TERM
# ---- Preflight -------------------------------------------------------------------
free_gb() { df -Pk "$1" | awk 'NR==2 {printf "%d", $4/1048576}'; }
existing_parent() { local p="$1"; while [[ ! -d "$p" ]]; do p="$(dirname "$p")"; done; echo "$p"; }
need_space() { # need_space <dir> <GB needed> <stage label>
local dir; dir="$(existing_parent "$1")"; local free; free="$(free_gb "$dir")"
if (( free < $2 + RESERVE_GB )); then
local msg="not enough disk for $3: need ~$2 GB + $RESERVE_GB GB reserve, only $free GB free on $dir"
if [[ $DRY_RUN -eq 1 ]]; then warn "$msg"; else die "$msg (partial work is kept; free space and re-run)"; fi
fi
}
preflight() {
[[ "$(uname -s)" == Darwin && "$(uname -m)" == arm64 ]] || warn "not Apple Silicon macOS; MLX conversion will not run"
[[ -f "$FASTVIDEO/scripts/checkpoint_conversion/convert_minimax_h3_mlx.py" ]] \
|| die "$FASTVIDEO is not a FastVideo checkout with convert_minimax_h3_mlx.py (need branch aryan/omniref-mlx-speed)"
command -v "$PYTHON" >/dev/null || die "python not found: $PYTHON"
if [[ $DRY_RUN -eq 0 ]]; then
PYTHONPATH="$FASTVIDEO" "$PYTHON" -I -c 'import sys; sys.path.insert(0, sys.argv[1]); import mlx.core, fastvideo.mlx_runtime.minimax_h3_conditioner' "$FASTVIDEO" \
|| die "$PYTHON cannot import mlx and fastvideo; pass --python of the FastVideo venv"
fi
if [[ $SKIP_DOWNLOAD -eq 0 ]]; then
command -v hf >/dev/null || die "'hf' CLI not found; run: $PYTHON -m pip install -U huggingface_hub"
fi
local mem_gb; mem_gb=$(( $(sysctl -n hw.memsize 2>/dev/null || echo 0) / 1073741824 ))
log "total RAM: ${mem_gb} GB"
(( mem_gb >= 24 )) || warn "RAM below 24 GB; int6/int8 conversion (peak ~21 GB) may fail"
local f out_gb=$((OUT_FIXED_GB + ENC_GB)) fmts=""
for f in $FORMATS; do
if [[ $f == bf16 ]] && (( mem_gb < 64 )); then
warn "skipping bf16: conversion needs ~40 GB free RAM and this Mac has ${mem_gb} GB (<64)"; continue
fi
out_gb=$((out_gb + $(fmt_gb "$f"))); fmts+="$f "
done
FORMATS="${fmts% }"
local src_gb=0; [[ $SKIP_DOWNLOAD -eq 0 ]] && src_gb=$SRC_GB
if [[ "$(df -Pk "$(existing_parent "$SOURCES")" | awk 'NR==2{print $1}')" == "$(df -Pk "$(existing_parent "$MODEL_DIR")" | awk 'NR==2{print $1}')" ]]; then
log "sources and outputs share a disk: need ~$((src_gb + out_gb)) GB total"
need_space "$MODEL_DIR" $((src_gb + out_gb)) "whole build"
else
need_space "$MODEL_DIR" "$out_gb" "outputs"
[[ $src_gb -eq 0 ]] || need_space "$SOURCES" "$src_gb" "downloads"
fi
log "formats to build: ${FORMATS:-none}"
}
# ---- Stage: download ---------------------------------------------------------------
sources_ok() { # all required source files present and well-formed (quiet)
helper shards-check "$S_OMNI/transformer_ref" diffusion_pytorch_model >/dev/null 2>&1 || return 1
local f
for f in transformer_ref/config.json scheduler/scheduler_config.json audio_scheduler/scheduler_config.json fastvideo_inference.json; do
[[ -s "$S_OMNI/$f" ]] || return 1; done
helper shards-check "$S_QAD/text_encoder" model >/dev/null 2>&1 || return 1
for f in text_encoder/config.json text_encoder/model.safetensors.index.json audio_vae/config.json audio_vae/diffusion_pytorch_model.safetensors \
processor/tokenizer.json tokenizer/tokenizer.json; do [[ -s "$S_QAD/$f" ]] || return 1; done
helper st-check "$S_QAD/audio_vae/diffusion_pytorch_model.safetensors" "$S_DEC/quality-36L/decoder-nvfp4.safetensors" \
"$S_DEC/fast-8L/decoder-nvfp4.safetensors" "$S_LVAE/lightvae-lite-h3-encoder.safetensors" >/dev/null 2>&1 || return 1
}
hf_get() { # hf_get <repo> <rev> <dir> <include...>
local repo="$1" rev="$2" dir="$3"; shift 3
local inc=(); local p; for p in "$@"; do inc+=(--include "$p"); done
mkdir -p "$dir"
log "hf download $repo @ ${rev:0:10}"
run hf download "$repo" --revision "$rev" "${inc[@]}" --local-dir "$dir"
}
stage_download() {
if [[ $SKIP_DOWNLOAD -eq 1 ]]; then
log "download: skipped (--skip-download); checking $SOURCES"
[[ $DRY_RUN -eq 1 ]] || sources_ok || die "sources under $SOURCES are incomplete (need omni-bf16/ nvfp4-qad/ vae-decoders/ lightvae/)"
return
fi
if [[ $DRY_RUN -eq 0 ]] && sources_ok; then log "download: all sources present and valid, skipping"; return; fi
need_space "$SOURCES" "$SRC_GB" "downloads"
hf_get "$REPO_OMNI" "$REV_OMNI" "$S_OMNI" 'transformer_ref/*' 'scheduler/*' 'audio_scheduler/*' fastvideo_inference.json
hf_get "$REPO_QAD" "$REV_QAD" "$S_QAD" 'text_encoder/*' 'processor/*' 'tokenizer/*' 'audio_vae/*'
hf_get "$REPO_DEC" "$REV_DEC" "$S_DEC" quality-36L/decoder-nvfp4.safetensors fast-8L/decoder-nvfp4.safetensors
hf_get "$REPO_LVAE" "$REV_LVAE" "$S_LVAE" lightvae-lite-h3-encoder.safetensors
[[ $DRY_RUN -eq 1 ]] || sources_ok || die "downloads finished but source validation failed; re-run to resume"
}
# ---- Stage: assemble root/, vae/, licenses ---------------------------------------------
copy_file() { # atomic, skip when identical
local src="$1" dst="$2"
[[ -f "$src" ]] || die "missing source file: $src"
if [[ -f "$dst" ]] && cmp -s "$src" "$dst"; then return 0; fi
mkdir -p "$(dirname "$dst")"
local tmp="$dst.partial.$$"; cp "$src" "$tmp" && mv -f "$tmp" "$dst"
}
copy_dir() { # copy_dir <src dir> <dst dir>: regular files only (skip AppleDouble / .cache)
local src="$1" dst="$2" f
[[ -d "$src" ]] || die "missing source dir: $src"
while IFS= read -r f; do copy_file "$src/$f" "$dst/$f"; done \
< <(cd "$src" && find -L . -type f ! -name '._*' ! -name '.DS_Store' ! -path './.cache/*' ! -name '*.metadata' | sed 's#^\./##' | sort)
}
stage_assemble() {
[[ $DRY_RUN -eq 0 ]] || { log "assemble: would copy root/ configs, vae/ weights, licenses and derive root/vae/config.json"; return 0; }
local r="$MODEL_DIR/root"
log "assembling root/, vae/, licenses"
copy_file "$S_OMNI/fastvideo_inference.json" "$r/fastvideo_inference.json"
copy_dir "$S_OMNI/scheduler" "$r/scheduler"
copy_dir "$S_OMNI/audio_scheduler" "$r/audio_scheduler"
copy_file "$S_OMNI/transformer_ref/config.json" "$r/transformer_ref/config.json"
copy_dir "$S_QAD/audio_vae" "$r/audio_vae"
copy_dir "$S_QAD/processor" "$r/processor"
copy_dir "$S_QAD/tokenizer" "$r/tokenizer"
copy_file "$S_DEC/quality-36L/decoder-nvfp4.safetensors" "$MODEL_DIR/vae/fasth3-quality-36L-decoder-nvfp4.safetensors"
copy_file "$S_DEC/fast-8L/decoder-nvfp4.safetensors" "$MODEL_DIR/vae/fasth3-fast-8L-decoder-nvfp4.safetensors"
copy_file "$S_LVAE/lightvae-lite-h3-encoder.safetensors" "$MODEL_DIR/vae/lightvae-lite-h3-encoder.safetensors"
helper vae-config "$S_LVAE/lightvae-lite-h3-encoder.safetensors" "$r/vae/config.json"
local l; for l in LICENSE LICENSE-Qwen3-VL NOTICE; do copy_file "$KIT_DIR/licenses/$l" "$MODEL_DIR/$l"; done
}
# ---- Stage: DiT conversion (sequential) -------------------------------------------------
convert_one() { # convert_one <fmt>
local fmt="$1" out="$MODEL_DIR/dit/$1" stage="$MODEL_DIR/dit/.partial-$1"
if [[ $DRY_RUN -eq 1 ]]; then
echo " (dry-run) (cd $FASTVIDEO && PYTHONPATH=$FASTVIDEO $PYTHON scripts/checkpoint_conversion/convert_minimax_h3_mlx.py --model-root $S_OMNI/transformer_ref --out $stage --formats $fmt --include-vsa) # then mv to $out"
return 0
fi
if [[ -s "$out/mlx_h3_dit.json" ]] && helper st-check "$out/mlx_h3_dit.safetensors" >/dev/null 2>&1; then
log "dit/$fmt: already converted and well-formed, skipping"; return 0
fi
need_space "$MODEL_DIR" "$(fmt_gb "$fmt")" "dit/$fmt conversion"
rm -rf "$out" "$stage" # incomplete or corrupt earlier attempt
lock_acquire
log "converting dit/$fmt (this takes a while)"
(cd "$FASTVIDEO" && run env PYTHONPATH="$FASTVIDEO" "$PYTHON" scripts/checkpoint_conversion/convert_minimax_h3_mlx.py \
--model-root "$S_OMNI/transformer_ref" --out "$stage" --formats "$fmt" --include-vsa)
if [[ $DRY_RUN -eq 0 ]]; then
helper st-check "$stage/$fmt/mlx_h3_dit.safetensors" || die "dit/$fmt conversion produced an invalid file"
mkdir -p "$MODEL_DIR/dit"; mv "$stage/$fmt" "$out"; rm -rf "$stage"
fi
lock_release
}
stage_dit() { local f; for f in $FORMATS; do timed "dit/$f" convert_one "$f"; done; }
# ---- Stage: NVFP4 encoder cache -----------------------------------------------------------
stage_encoder() {
local out="$MODEL_DIR/root/text_encoder"
if [[ $DRY_RUN -eq 1 ]]; then
echo " (dry-run) $PYTHON -c 'export_mlx_h3_nvfp4_encoder($S_QAD/text_encoder, $out)'; then set source_dir=$ENCODER_SOURCE_FIELD"
return 0
fi
if [[ -s "$out/model.safetensors" && -s "$out/mlx_h3_nvfp4_encoder.json" ]] \
&& helper st-check "$out/model.safetensors" >/dev/null 2>&1; then
log "text_encoder cache: present and well-formed, skipping export"
else
need_space "$MODEL_DIR" "$ENC_GB" "encoder export"
rm -rf "$out" "$MODEL_DIR"/root/.text_encoder.partial-* # export refuses a non-empty target
lock_acquire
log "exporting NVFP4 encoder cache (format v2)"
run env PYTHONPATH="$FASTVIDEO" "$PYTHON" -c '
import sys
from fastvideo.mlx_runtime.minimax_h3_conditioner import export_mlx_h3_nvfp4_encoder
export_mlx_h3_nvfp4_encoder(sys.argv[1], sys.argv[2])' "$S_QAD/text_encoder" "$out"
lock_release
fi
# Make the manifest independent of where sources lived (same edit as our reference build).
[[ $DRY_RUN -eq 1 ]] || helper rewrite-source "$out/mlx_h3_nvfp4_encoder.json" "$ENCODER_SOURCE_FIELD"
}
# ---- Stage: verify ----------------------------------------------------------------------------
stage_verify() {
[[ $DRY_RUN -eq 0 ]] || { log "verify: skipped in dry-run"; return 0; }
local exp; exp="$(mktemp)"; printf '%s\n' "$EXPECTED_SHA256" > "$exp"
log "verifying SHA-256 against the reference build"
local rc=0; helper verify "$MODEL_DIR" "$exp" $FORMATS || rc=$?
rm -f "$exp"; return $rc
}
# ---- Main -------------------------------------------------------------------------------------------
log "model dir: $MODEL_DIR | sources: $SOURCES | python: $PYTHON | formats: $FORMATS"
preflight
timed download stage_download
timed assemble stage_assemble
stage_dit
timed encoder stage_encoder
VERIFY_RC=0; timed verify stage_verify || VERIFY_RC=$?
if [[ $VERIFY_RC -eq 0 && $SKIP_DOWNLOAD -eq 0 && $KEEP_SOURCES -eq 0 && $DRY_RUN -eq 0 ]]; then
log "removing downloaded sources $SOURCES (use --keep-sources to retain)"; rm -rf "$SOURCES"
fi
echo; echo "================ SUMMARY ================"
printf 'timings:\n'; printf ' %s\n' ${TIMINGS[@]+"${TIMINGS[@]}"}
echo "model dir: $MODEL_DIR"
(( ${#WARNINGS[@]} == 0 )) || { echo "warnings:"; printf ' - %s\n' "${WARNINGS[@]}"; }
if [[ $DRY_RUN -eq 1 ]]; then echo "dry-run: nothing was downloaded or converted"; exit 0; fi
if [[ $VERIFY_RC -ne 0 ]]; then
echo "RESULT: VERIFICATION FAILED. Downloaded-file hash mismatches mean a corrupt/changed download:"
echo "delete the named files under $SOURCES and $MODEL_DIR and re-run."; exit 1
fi
echo "RESULT: OK"
FIRST_FMT="${FORMATS%% *}"
cat <<EOF
Next, from $KIT_DIR (use the FastVideo venv python):
$PYTHON run_matrix.py --self-test --data-root ~/omniref-handoff
$PYTHON run_matrix.py --smoke --model-dir "$MODEL_DIR" --fastvideo-root "$FASTVIDEO" --data-root ~/omniref-handoff
$PYTHON run_matrix.py --model-dir "$MODEL_DIR" --fastvideo-root "$FASTVIDEO" --data-root ~/omniref-handoff --out ./results-mystudio
(DiT format used by default: ${FIRST_FMT:-int6}; see run_matrix.py --help for selecting int8/bf16.)
EOF
|