facebook/vjepa2-vitl-fpc16-256-ssv2
(375M, MIT) — Meta’s video world model: a self-supervised video encoder (JEPA — learns by
predicting in representation space, not pixels) with an attentive pooler + Something-Something-v2
action-recognition head (174 physical-interaction classes: pushing, lifting, covering,
rolling…). A 16-frame clip goes in, an action label comes out — the zoo’s first video
understanding model, a category with no MLX port and no Apple stock path.
Bundle: 🤗 mlboydaisuke/VJEPA2-ViTL-SSv2-CoreAI
— macOS (~708 MB fp16 JIT) + iOS (~1.4 GB, AOT-precompiled for iPhone), labels.json
alongside. Catalog id: vjepa2-vitl-ssv2.
⚡ One line — this model is the default behind the kit’s task op
(import CoreAIOps; no session, no model plumbing, downloads on first use):
let actions = try await CoreAI.recognizeAction(videoAt: videoURL)
Twenty ops, one shape — Cookbook.
▶️ Run it (source) — the ActionCamera runner (live camera action recognition, one app for every video model in the catalog):
git clone https://github.com/john-rocky/coreai-kit
open coreai-kit/Examples/ActionCamera/ActionCamera.xcodeproj
# → Run, then pick "V-JEPA 2 ViT-L (SSv2)" in the model picker
# agents / headless (macOS):
cd coreai-kit/Examples/ActionCamera
swift run action-cli --model vjepa2-vitl-ssv2 --video sample.mp4
💻 Build with it — complete; the glue is kit API, copy-paste runs:
import CoreAIKitVision
let recognizer = try await ActionRecognizer(catalog: "vjepa2-vitl-ssv2")
let actions = try await recognizer.classify(videoAt: videoURL, topK: 3)
// actions: ranked [Prediction] — .label ("Pushing [something] from left to right"),
// .probability; 174 SSv2 classes, fully on-device
The take-home is Examples/ActionCamera/Sources/QuickStart.swift
— this exact code as one typed function, no UI; the CLI is an argument shell over it, and
the GUI classifies a rolling 16-frame clip from CameraFeed.
Live camera? Keep the last 16 CameraFeed frames and call classify(frames:) — other
frame counts are uniformly resampled to 16. The bundled sample.mp4 is a synthetic
clip (a hand pushing a block); point --video at real footage for real results.
Integration checklist
https://github.com/john-rocky/coreai-kit → product CoreAIKitVisionNSCameraUsageDescription — only for the live camera; the snippet needs nonedownloadProgress callback)| Platform | Latency (16-frame clip) |
|---|---|
| M4 Max, GPU | ~150–180 ms (load 0.15 s) |
| iPhone 17 Pro (AOT h18p) | ~0.34 s warm |
Parity: engine vs the HF fp16 reference cos 0.999996, top-5 identical; plus a semantic
gate — a synthetic square moving up vs down flips the top labels
(Moving [something] up ↔ …down), proving motion understanding on-engine with no dataset
(conversion/vjepa2/gate_semantic.py).
One stateless graph: pixel_values_videos [1,16,3,256,256] → logits [1,174]
(VJEPA2ForVideoClassification, direct export). Host does the preprocessing: 16 frames
uniform-sampled, aspect-fill 256², RGB 0..1, ImageNet mean/std — the model does not
normalize internally. One overlay was needed: 3D RoPE’s no-op squeeze(-1) on a non-1 dim
maps to ShrinkDims and fails — patched out, math unchanged (see
conversion/vjepa2/export_fp16.py and
knowledge/video-world-models-vjepa2.md).
Live camera → rolling 16-frame clip → label: the kit’s
ActionCamera runner
(GUI + action-cli), or the zoo’s bespoke coreai-video app
(iPhone-verified).