Native macOS application for local AI video generation using LTX-2.3 on Apple Silicon via MLX. No cloud required — everything runs on-device.
A local alternative to Lightricks LTX Desktop that replaces NVIDIA/CUDA inference with MLX on Apple Silicon unified memory. The official macOS version requires a cloud API — this project eliminates that dependency.
Stack: SwiftUI (native macOS app) + Python FastAPI backend + MLX inference engine (LTX-2.3, 22B params).
| Component | Minimum | Recommended |
|---|---|---|
| macOS | 14.0 Sonoma | 15 Sequoia or later |
| RAM | 32 GB | 64 GB+ |
| Chip | Apple M1 Pro | M3 Max / M4 Ultra |
| Disk | 60 GB free | 100 GB+ free |
| Xcode | 15.0+ | Latest |
| Python | 3.12+ | 3.12 |
16 GB machines: very limited — low resolutions only.
Try LTX Desktop using a pre-compiled development build
⚠️ On first launch, macOS may show a security warning because the dev build is not notarized by Apple
Choose to keep the App and browse toSystem Settings > Privacy & Securityand clickOpen Anyway.
brew install ffmpeg uv python@3.12git clone <repo-url>
cd ltx-desktop-macos
bash scripts/setup.shbash scripts/download_models.shThis downloads:
dgrauet/ltx-2.3-mlx-q8(~28 GB) — pre-converted MLX video generation modelmlx-community/gemma-3-12b-it-4bit(~6 GB) — text encoder (also used for prompt enhancement)
cd backend
.venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 8000open app/LTXDesktop.xcodeprojRun from Xcode (Cmd+R). The SwiftUI app auto-connects to the backend on localhost:8000.
SwiftUI App (native macOS)
|
| HTTP + WebSocket (localhost:8000)
|
Python FastAPI Backend
|
+-- MLX Engine (DiT inference on Apple Silicon)
+-- ffmpeg (video encoding / audio mixing)
Two-subprocess model for 32GB machines:
- Subprocess A: Gemma 3 12B 4-bit text encoding (~8.7GB peak) → exits, frees GPU
- Subprocess B: Transformer + VAE generation (~12.6GB peak)
The backend runs as a separate process managed by the SwiftUI app's ProcessManager. Crash isolation means an OOM in the ML pipeline kills only the backend — the UI stays alive and offers a restart button.
- Text-to-Video (T2V): prompt → video with synchronized audio
- Image-to-Video (I2V): drag-and-drop source image conditions the first frame
- Synchronized audio: audio generated in single pass (vocoder output, quality WIP)
- Prompt enhancement: Gemma 3 12B rewrites short prompts into detailed descriptions (via ltx-core-mlx)
- Progressive preview: intermediate diffusion frames streamed to UI every 2 steps
- Two-stage upscale: generate at half resolution, neural 2x upscale (single safetensors file from Lightricks/LTX-2.3)
- Batch generation queue: priority-based job queue with cancel support
- History view: video archive with thumbnails, metadata, and delete
- Model management: download/delete models from Settings, disk usage tracking
- Memory monitor: real-time Metal memory stats with color-coded warnings
- Streaming VAE decode: frames decoded one-by-one into ffmpeg pipe (never all in RAM)
- Export: MP4 with H.264 encoding + AAC audio
- LoRA: UI exists (scan, toggle, strength slider) but untested with real LTX-2.3 LoRA models
- Retake / Extend: real inference via ltx-pipelines-mlx, endpoints need wiring
- FCPXML export: endpoint exists but untested
| Model | Repo | Role | Size |
|---|---|---|---|
| LTX-2.3 (int8) | dgrauet/ltx-2.3-mlx-q8 |
Video generation (transformer + VAE + audio + vocoder) | ~28 GB |
| Gemma 3 12B IT (4-bit) | mlx-community/gemma-3-12b-it-4bit |
Text encoder + prompt enhancement | ~6 GB |
| LTX-2.3 Spatial Upscaler | Lightricks/LTX-2.3 (single file) |
Neural 2x upscale | ~1 GB |
The pipeline uses ltx-core-mlx and ltx-pipelines-mlx for inference (conditioning, denoising loop, VAE encoding/decoding).
Metal memory fragmentation is the #1 stability risk. The backend implements:
aggressive_cleanup()at every pipeline stage boundary- Streaming VAE decode to ffmpeg pipe — never all frames in RAM
- Periodic model reload every 5 generations to reclaim fragmented Metal buffers
- Prompt enhancement via Gemma 3 12B (same model as text encoder, handled by library)
Measured on Apple M2 Pro 32 GB (int8 quantized distilled model, 8 steps):
| Resolution | Frames | Time |
|---|---|---|
| 384x256 | 9 | ~42s |
| 768x512 | 97 | ~495s (~8 min) |
| 1280x704 | 97 | ~1650s (~27 min) |
Marathon test: 10 consecutive 97-frame generations at 768x512 — no OOM, stable timing (484-507s per gen).
LTX-2.3 responds best to structured, detailed prompts:
- Subject: appearance, clothing, expression
- Action: specific, chronological movements
- Environment: location, lighting, atmosphere
- Camera: angle and motion (dolly, pan, static, tracking)
- Style: cinematic, realistic, animated, color grading
- Audio (optional): sounds, music, dialogue
Example:
A young woman with short brown hair wearing a white linen shirt walks along a sun-drenched coastal path. She pauses to look at the sea, smiling slightly. Gentle ocean breeze moves her hair. Camera slowly tracks alongside her. Warm golden hour light. Soft ambient waves and distant seagulls. Cinematic, shallow depth of field.
Use the Enhance button (Cmd+E) to auto-expand short prompts.
- Audio quality tuning (vocoder output noisy)
- LoRA testing with real LTX-2.3 compatible models
- Video retake & extend endpoint wiring (library support ready)
- FCPXML export for Final Cut Pro / DaVinci Resolve
- Performance: persistent model server for mx.compile() (currently disabled — incompatible with subprocess-per-gen architecture)
- Simple timeline editor (if demand warrants it)
- V2V, A2V, keyframe interpolation
- ~8 min per generation at 768x512 — mx.compile() disabled (tracing overhead lost per subprocess)
- Audio quality: vocoder output can sound noisy
- 32 GB RAM: text encoder and video model cannot coexist — two-subprocess architecture is mandatory
- No 16 GB support: model weights alone are ~21 GB
Apache-2.0 — same as LTX Desktop by Lightricks.
The LTX-2.3 model weights are subject to the LTX Model License.