Fable created novel 4D splat format
Structure
A .splat4d file has three parts. A small header carries the bounds, the quantization steps, and a chunk index with absolute byte ranges - everything a client needs to plan its fetches. The static section holds the per-splat masks and base values: fetch it once and the complete scene is on screen. The rest is one self-contained GOP chunk per ~1 s of video, with key streams laid out before delta streams.
"SP4D" + header JSON
STATIC section β full first view
GOP chunk 0 [keys][deltas]
GOP chunk 1
β¦
Error Bounds
Every attribute of every splat in every decoded frame is within a user-chosen bound of the source - not on average, not in PSNR: pointwise and deterministic.
| attribute | bound | default |
|---|---|---|
| position | Β± millimeters, Lβ per axis | Β±2 mm |
| color RGB | Β± 8-bit levels per channel | Β±4/255 |
| opacity | Β± 8-bit levels | Β±4/255 |
| rotation | Β± quaternion component (units of 1/128, up to sign) | exact (Β±0) |
| scale | Β± relative %, per axis | Β±2% |
Mechanism
SZ/ZFP-style error-bounded quantization (step = 2Γbound β error β€ bound by construction). After quantization everything is integer math - temporal deltas can never drift, and the Rust and JavaScript decoders reconstruct bit-identical values.
HTTP Delivery
The format is designed for plain HTTP Range requests against S3 / GCS / R2 / any static host - no server logic, no manifest files, no video container. A client needs exactly:
bytes=0-262143 β magic + header JSON (all byte offsets are absolute)
Object stores support this natively. For browser clients, set CORS to allow the Range header and expose Content-Range:
[{
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["https://your-site"],
"AllowedHeaders": ["Range"],
"ExposeHeaders": ["Content-Range", "Content-Length", "Accept-Ranges"]
}]
Payloads are already zstd-compressed inside the container, so store objects with no Content-Encoding - range math stays byte-exact and nothing double-compresses.
Source Data
Eight sequences from three independent capture pipelines: Dynamic 3D Gaussians (CMU Panoptic dome - juggle, boxes, softball, tennis), Neu3D cooking scenes via SpacetimeGaussians/splaTV (flame = backyard BBQ, sear = kitchen chef), and Technicolor (birthday party, 659k splats) - all converted to per-frame antimatter15 .splat files (32 B/splat), 20 fps.
splat4d encodes use default bounds (Β±2 mm / Β±4 color / exact rot / Β±2% scale); gzip is per-frame -9. For context, the best generic lossless baseline (zstd-19 --long over the whole series) reaches only 2.5Γ. Full methodology and more baselines: BENCHMARKS.md.
Performance
Loading benchmarks.json⦠Raw WebGPU, a line-by-line port of the antimatter15/splat renderer, pixel-verified against it.
| metric | local | throttled 50 Mbps |
|---|---|---|
| full first view (header + static section) | 141β157 ms | 791 ms |
| scrub into unbuffered region β keyframe visible | - | 145 ms |
| playback | 60 fps @ 336k splats Β· worker decode 2.5β27 ms/frame Β· sort 1β25 ms |
Encoding
A time series of antimatter15 .splat frames β one small, seekable file:
# Python (pip install splats4d)
splat4d encode -i frames_dir -o out.splat4d
Comments
No comments yet. Start the discussion.