jc-builds/Wan2.2-TI2V-5B-iOS
Wan 2.2 TI2V 5B — iOS bundle
<p align="center"> <a href="https://github.com/haplollc/Mirage"> <img alt="Mirage" src="https://img.shields.io/badge/Runs%20on-Mirage-orange" /> </a> <a href="https://huggingface.co/Wan-AI/Wan2.2-TI2V-5B"> <img alt="Upstream" src="https://img.shields.io/badge/Upstream-Wan--AI%2FWan2.2--TI2V--5B-blue" /> </a> <img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-lightgrey" /> <img alt="Params" src="https://img.shields.io/badge/params-5B-purple" /> <img alt="Modes" src="https://img.shields.io/badge/modes-T2V%20%2B%20I2V-green" /> </p>
A pre-flighted bundle of Wan 2.2 TI2V 5B + UMT5-XXL (text encoder) + the Wan 2.2 high-compression VAE, quantized to fit the top tier of Apple hardware and run via **Mirage** — the on-device diffusion engine for iOS / macOS / visionOS.
This is video generation with no server. One model does both jobs: text→video and image→video (animate a still photo) from the same weights. Wan 2.2 TI2V 5B is Alibaba's dense 5B video diffusion transformer paired with a 16×16×4 high-compression VAE — the compression ratio that makes phone-side denoising and decode tractable at all.
What's inside
Total bundle size: ~8.5 GB. Peak memory at generation time depends heavily on resolution × frame count; the VAE decode of the full frame stack is the spike — enable tiled decode on memory-constrained devices.
Quick start (Mirage)
import Mirage
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let engine = try Engine(models: ModelFiles(
diffusionModel: docs.appendingPathComponent("Wan2.2-TI2V-5B-Q4_K_M.gguf"),
vae: docs.appendingPathComponent("wan2.2_vae.safetensors"),
t5Encoder: docs.appendingPathComponent("umt5-xxl-encoder-Q4_K_M.gguf")
))
// Text → video
let video = try await engine.generateVideo(.init(
prompt: "a golden retriever puppy running through shallow ocean waves at sunset, slow motion, cinematic",
width: 480, height: 832, // Wan's native 480p — off-distribution sizes degrade hard
frames: 33, // must be 4n+1 (temporal compression is 4×)
steps: 20,
cfgScale: 6.0,
flowShift: 3.0
))
// → ordered RGB frames; fps is an encode-time choice —
// write them to .mp4 with AVAssetWriter (16 fps is Wan's native rate)
// Image → video: pass an init image and the same call animates it.Frame-count rule
The VAE compresses time 4×, so `frames` must be `4n + 1`: 13, 17, 21, 25, 29, 33, … A 33-frame clip at 16 fps is ~2 seconds of video. Passing an even count will be rounded by the engine.
Prompting guide
Wan conditions on UMT5-XXL, a multilingual instruction-grade encoder — like all modern DiTs it rewards full-sentence, cinematography-flavored prompts over tag soup:
- Order matters: subject → motion → camera → scene. The model weighs the start of the prompt most heavily, so lead with what matters most.
- Name the motion. Video models allocate capacity to change-over-time. "waves rolling in, hair blowing in the wind, camera slowly dollying right" beats a static scene description.
- Lead with the subject, follow with the camera. "A red fox stalking through snow, tracking shot, shallow depth of field."
- One scene per clip. 2-5 seconds is a shot, not a film. Prompts describing scene cuts produce mush.
- English and Chinese both work — Wan was trained bilingually, and the strongest negative prompt in the ecosystem is the Chinese default below.
The upstream default negative prompt (recommended as-is):
色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走(It reads: garish tones, overexposure, static image, blurry details, subtitles, watermark-style artifacts, gray cast, worst quality, JPEG residue, malformed anatomy, fused fingers, still frame, cluttered background, walking backwards — the classic video-model failure modes.)
Performance (measured via stable-diffusion.cpp on an M2 Mac, 24 GB)
Phase timings for a 480×832 clip (Wan's native 480p geometry), 13 frames, 20 steps — diffusion on Metal with flash attention, text encoder + VAE on CPU with tiled decode (the memory-safe mobile configuration):
End-to-end: roughly 25 minutes per ~0.8 s clip on an M2. This is a patience feature, not an instant one — the point is that it runs at all with zero server involvement. The VAE decode dominates; a TAE-style tiny decoder (taehv) is the known path to cutting that to seconds and is the first planned improvement.
Resolution is a hard constraint, not a dial. Off-distribution sizes (e.g. 480×320) sample recognizable subjects wrapped in heavy artifacts. Stick to the trained 480p geometry: 480×832 portrait / 832×480 landscape, 13-33 frames, 15-25 steps.
Memory: untiled decode at 480×832×13 allocates ~20.7 GB — enable tiled decode everywhere. Default 32-tiles measured ~12.7 GB (seam-free output); smaller tiles cut it further for phone-class ceilings.
Gate availability on physical RAM, not device model:
ProcessInfo.processInfo.physicalMemory >= 12 * 1024 * 1024 * 1024Sample output
A real 13-frame clip from this exact Q4 bundle on an M2 Mac — 480×832, 20 steps, tiled CPU decode:
Prompt: "a golden retriever puppy running through shallow ocean waves at sunset, splashing water, slow motion, cinematic lighting"
<video src="https://huggingface.co/jc-builds/Wan2.2-TI2V-5B-iOS/resolve/main/sample_video.mp4" controls muted loop type="video/mp4"></video>
And single-frame generation (Wan does text-to-image too — frames: 1), 480×320, 20 steps:
Prompt: "a golden retriever puppy sitting on a beach at sunset, photorealistic"
Why this bundle exists
The official Wan 2.2 release is PyTorch + Diffusers — brilliant on an H100, unrunnable on a phone. Getting it on-device requires:
- An engine that speaks GGUF video DiTs — stable-diffusion.cpp grew
vid_gensupport for the Wan family in 2025, and it runs on ggml-metal - The matching parts: TI2V 5B uses its own high-compression VAE (
wan2.2_vae, not the Wan 2.1 VAE every other Wan model uses) and the UMT5-XXL encoder — mixing these up produces noise - Quants sized for a 12 GB memory ceiling rather than a 24 GB GPU
Picking those apart from three upstream repos takes effort. This bundle packages the working combination once, verified end-to-end on Apple Silicon.
Provenance
License
Apache 2.0 throughout — bundle, documentation, and all upstream weights. Safe for commercial, on-device use.
