LTX-2.5 text-to-video locally on Apple Silicon in one command — with audio, no ComfyUI/CUDA. 16x faster than PyTorch-on-MPS (53s vs 853s) via macOS 26 watchdog + eval-guard fixes.

README.md

LTX-2.5 on Apple Silicon, one command

Generate video — with audio — locally on your Mac. No ComfyUI, no CUDA. The first run bootstraps everything itself: the MLX runtime, the Python env, and a one-time ~36 GiB weight download.

curl -fsSL https://gist.githubusercontent.com/DanielHauschildt/9ad1d7cef482ed508a121881280b74dd/raw/generate -o generate
chmod +x generate
./generate "A wide shot frames a rainy city intersection at dusk, neon signs reflecting on wet asphalt. A young woman in a yellow raincoat walks toward camera, gripping a folded newspaper, while cars hiss past behind her. Soft synth music and distant traffic fill the air. A hard cut transitions to a medium close-up of her face under the hood, raindrops catching the neon as she looks off-screen left; the synth score continues across the cut, traffic muffled. She whispers, “He's late.” Another hard cut jumps to a low-angle shot of a man's scuffed boots stepping into a puddle at the curb; the music drops to a low drone. He lifts his head into frame — short dark hair, soaked jacket — and smiles toward her off-screen as a bus rumbles past." \
  --width 768 --height 512 --frames 241 --output rainy_intersection.mp4

LTX-2.5 does multi-shot scenes natively — describe the shots in order and quoted dialogue becomes speech. Give them room: 241 frames ≈ 10 s fits three shots.

Needs: Apple Silicon Mac with 32 GB+ RAM (24 GB works with --low-ram) · brew install uv ffmpeg · ~40 GiB disk.

Rules: width/height divisible by 32 · frames = 8n+1 (33, 65, 97, 121, …) · extra args pass through to the ltx-2-mlx CLI.

Speed (M3 Max, 64 GB): 1.4 s clip in ~1 min · 5 s 768×512 clip in ~5–8 min. That's ~16× faster than PyTorch-on-MPS — two non-obvious fixes are baked into the script, documented in its comments.

Credits

Lightricks LTX-2.5 (weights, LTX-2.x Community License — free for commercial use under $10M ARR) · dgrauet/ltx-2-mlx (MLX runtime) · MrMofer's LTX-2.5 port + q8 conversion. No weights are redistributed here; the script downloads them from HuggingFace under their own license.

generate

#!/bin/zsh
# LTX-2.5 text-to-video on Apple Silicon — clone-and-run launcher.
#
# First run bootstraps everything: clones the pinned MLX runtime, lets uv
# create the Python env, and downloads the ~36 GiB q8 weight subset from
# HuggingFace (ungated, no login). Subsequent runs go straight to generation.
#
# Usage:
# ./generate "A sailboat crossing a calm sea at golden hour"
# ./generate "prompt" --width 768 --height 512 --frames 121 --output clip.mp4
#
# Constraints: width/height divisible by 32, frames = 8n+1 (33, 65, 97, 121...).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
RUNTIME="$ROOT/.runtime"
WEIGHTS="$ROOT/models/ltx-2.5-mlx-q8"
PROMPT="${1:?usage: generate \"prompt\" [ltx-2-mlx args...]}"
shift
# The MLX runtime with LTX-2.5 support, pinned to a validated commit.
RUNTIME_REPO="https://github.com/MrMoferFRAN/ltx-2-mlx.git"
RUNTIME_COMMIT="57952288076766abe27dda3a774b2c24f7346977"
WEIGHTS_REPO="MrMofer/ltx-2.5-mlx-q8"
for tool in git uv ffmpeg; do
command -v "$tool" >/dev/null || { echo "error: '$tool' is required — install it with: brew install $tool" >&2; exit 1; }
done
if [[ ! -d "$RUNTIME" ]]; then
echo "[bootstrap] Cloning MLX runtime (pinned $RUNTIME_COMMIT) ..."
git clone --quiet "$RUNTIME_REPO" "$RUNTIME"
git -C "$RUNTIME" checkout --quiet "$RUNTIME_COMMIT"
fi
if [[ ! -f "$WEIGHTS/transformer-distilled.safetensors" ]]; then
echo "[bootstrap] Downloading LTX-2.5 q8 weights (~36 GiB, one time) ..."
echo " License: LTX-2.x Community License — https://huggingface.co/$WEIGHTS_REPO"
uv run --project "$RUNTIME" python - "$WEIGHTS_REPO" "$WEIGHTS" <<'PY'
import sys
from huggingface_hub import snapshot_download
repo, dest = sys.argv[1], sys.argv[2]
# Distilled-pipeline subset only: skips the dev transformer and the stage-2
# LoRA (needed only for CFG modes), saving ~27 GiB.
snapshot_download(
repo,
local_dir=dest,
allow_patterns=[
"transformer-distilled.safetensors",
"connector.safetensors",
"text_encoder/*",
"vae_encoder.safetensors",
"vae_decoder.safetensors",
"audio_vae.safetensors",
"vocoder.safetensors",
"spatial_upscaler_x2.safetensors",
"temporal_upscaler_x2.safetensors",
"duration_head.safetensors",
"*.json",
"LICENSE.md",
],
)
PY
fi
# AGX_RELAX_CDM_CTXSTORE_TIMEOUT works around the macOS 26 + MLX 0.31 GPU
# watchdog stall (dgrauet/ltx-2-mlx#75); the per-step cost is otherwise
# 25-130x higher. With the watchdog relaxed, the runtime's per-block eval
# guards are redundant on >=32 GB machines, so they are disabled too.
exec env \
AGX_RELAX_CDM_CTXSTORE_TIMEOUT=1 \
LTX2_DIT_EVAL_EVERY=0 \
LTX2_GEMMA_EVAL_EVERY=0 \
uv run --project "$RUNTIME" ltx-2-mlx generate \
--model "$WEIGHTS" \
--distilled --frame-rate 24 \
--prompt "$PROMPT" \
"$@"
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论