Make Gaussian Splats production‑ready.
Open-source CLI and viewer SDK that compresses real Gaussian-Splat assets 22× without losing what you can see, ships them through standards-aligned glTF + SPZ, and proves every claim with a deterministic visual-fidelity benchmark.
Bonsai scene · 1.16M splats · 273 MB → 12 MB at the
web-mobile preset.
Mean colour distance vs. the lossless baseline across 8 orbit frames. Below the 3% attentive-observer threshold.
Full optimize + pack pipeline on bonsai. Single-threaded Rust;
releases tagged with a deterministic BLAKE3 corpus hash.
Install
$git clone https://github.com/montabano1/SplatForge && cd SplatForge && cargo build --release -p splatforge-cli Quickstart
Four commands to go from a raw .ply to a SplatBench entry. Full
reference in the README.
-
Build from source — Rust toolchain. macOS, Linux, Windows.
git clone https://github.com/montabano1/SplatForge && cd SplatForge && cargo build --release -p splatforge-cli -
Pick a preset. web-mobile is the everyday default; size-min squeezes harder.
splatforge optimize scene.ply --preset web-mobile --out scene.gltf -
The viewer SDK is a tiny TS package — WebGPU primary, WebGL2 fallback.
pnpm add @splatforge/viewer # then in your app: # new SplatForgeViewer({ canvas }).load('scene.gltf') -
Reproduce the leaderboard byte-for-byte on your machine — same corpus, same hashes.
make bench-splatbench
SplatBench · Leaderboard
28 scenes — 14 real
(Mip-NeRF 360 + Dany Bittel cluster_fly LOD ladder, all CC-BY-4.0,
measured via the v2 ingest harness in apps/bench-ingest) and
14 deterministic synthetic probes for
per-class failure modes (texture, transparency, motion, depth, banding, foliage,
specular, lowlight, portrait, …) — run through the
full analyze → optimize → pack pipeline at each preset. Compression is
measured against the raw .ply; fidelity is mean CIE ΔE94 over 8
deterministic orbit frames rendered through @splatforge/viewer, scaled
0–1 against the published 3% perceptibility threshold. Every scene
is identified by a BLAKE3 hash of its canonical IR so runs reproduce byte-for-byte.
QAT-PLY (Scaffold-GS lossless): 37.3% aggregate PLY compression with PSNR gain on every scene tested (6/6). Per-scene save range 33.8–40.5%, ΔPSNR range +0.032 dB to +0.581 dB (mean +0.172 dB). All six scenes strictly improve on PSNR, SSIM, and LPIPS — see the new column below.
pro — splat-aware perceptual score
(catches floater + edge-loss artifacts ΔE94 misses).
premium — differentiable repack
PSNR delta vs naive opacity-prune at the same byte budget.
Negative cells (translucent volumes) are a known failure mode
where opacity-prune is structurally near-optimal; we publish them
honestly rather than tune them away.
Values are published; both columns require splatforge-pro to
reproduce.
| Scene | Class | Source | Splats | Input | SPZ out | Ratio | splat-transform vs | QAT-PLY scaffold-gs | Fidelity (ΔE94) | ML Score pro | Repack ΔPSNR premium | analyze |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cluster_fly_xxl | indoor-close-up | REAL | 3,506,799 | 789.3 MB | 25.3 MB | 31.21× | 15.79× +98% | — | pending | — | — | 0 ms |
| splatbench_banding_proxy | smooth-color-gradient | synth | 10,000 | 2.4 MB | 91.1 KB | 26.60× | 5.23× +409% | — | 0.03% | 95.17% | +12.62 dB | 29 ms |
| cluster_fly_xl | indoor-close-up | REAL | 624,180 | 140.5 MB | 5.4 MB | 25.85× | 12.77× +102% | — | pending | — | — | 0 ms |
| splatbench_floater_proxy | noisy-capture | synth | 250,000 | 59.1 MB | 2.3 MB | 25.84× | 10.69× +142% | — | 0.07% | 92.66% | -2.23 dB | 248 ms |
| splatbench_texture_proxy | high-frequency-texture | synth | 15,000 | 3.5 MB | 142.6 KB | 25.48× | 6.47× +294% | — | 0.09% | 94.26% | +8.27 dB | 32 ms |
| bicycle_mipnerf360_iter7k | outdoor-scene | REAL | 3,616,103 | 855.3 MB | 33.6 MB | 25.46× | — | — | 2.86% | 0.00% | +5.80 dB | 4.46 s |
| cluster_fly_l | indoor-close-up | REAL | 301,958 | 68.0 MB | 2.7 MB | 24.87× | 10.37× +140% | — | pending | — | — | 0 ms |
| splatbench_depth_proxy | depth-bimodal | synth | 15,000 | 3.5 MB | 149.6 KB | 24.30× | 6.88× +253% | — | 0.02% | 95.34% | +21.91 dB | 33 ms |
| cluster_fly_m | indoor-close-up | REAL | 145,617 | 32.8 MB | 1.4 MB | 23.93× | 7.49× +219% | — | pending | — | — | 0 ms |
| stump_mipnerf360_iter7k | outdoor-scene | REAL | 3,807,536 | 900.5 MB | 39.2 MB | 22.97× | 18.40× +25% | — | pending | — | — | 3.93 s |
| bonsai_mipnerf360_iter7k | indoor-real-estate | REAL | 1,157,141 | 273.7 MB | 12.0 MB | 22.81× | 16.53× +38% | — | 0.60% | 46.51% | +7.43 dB | 1.24 s |
| splatbench_portrait_proxy | salient-region-portrait | synth | 12,000 | 2.8 MB | 129.0 KB | 22.55× | 5.77× +291% | — | 0.04% | 95.12% | +24.04 dB | 15 ms |
| splatbench_specular_proxy | specular-highlights | synth | 12,000 | 2.8 MB | 132.3 KB | 21.97× | 5.82× +277% | — | 0.04% | 95.14% | +15.41 dB | 16 ms |
| splatbench_motion_proxy | anisotropic-streak | synth | 12,000 | 2.8 MB | 133.5 KB | 21.79× | 5.71× +282% | — | 0.15% | 91.49% | +10.51 dB | 30 ms |
| splatbench_dense_proxy | dense-large-scene | synth | 2,000,000 | 473.0 MB | 21.7 MB | 21.75× | — | — | 0.00% | 95.54% | +6.99 dB | 2.18 s |
| cluster_fly_s | indoor-close-up | REAL | 25,627 | 5.8 MB | 277.0 KB | 21.33× | 6.06× +252% | — | pending | — | — | 0 ms |
| splatbench_indoor_proxy | indoor-real-estate | synth | 100,000 | 23.7 MB | 1.1 MB | 20.58× | 5.91× +248% | — | 0.03% | 95.12% | +6.58 dB | 105 ms |
| splatbench_product_proxy | product-scan | synth | 10,000 | 2.4 MB | 118.2 KB | 20.50× | 4.96× +313% | — | 0.02% | 95.28% | +14.69 dB | 11 ms |
| splatbench_lowlight_proxy | low-light-dynamic-range | synth | 8,000 | 1.9 MB | 96.5 KB | 20.10× | 6.56× +206% | — | 0.03% | 95.27% | +13.97 dB | 11 ms |
| splatbench_outdoor_proxy | outdoor-scene | synth | 500,000 | 118.3 MB | 6.0 MB | 19.67× | 13.88× +42% | — | 0.02% | 95.16% | +5.60 dB | 483 ms |
| splatbench_transparency_proxy | volumetric-translucency | synth | 25,000 | 5.9 MB | 337.2 KB | 17.96× | 5.39× +233% | — | 0.07% | 94.69% | -8.30 dB | 51 ms |
| splatbench_foliage_proxy | dense-translucency | synth | 30,000 | 7.1 MB | 412.3 KB | 17.63× | 6.04× +192% | — | 0.09% | 93.96% | +10.35 dB | 34 ms |
| bonsai_scaffold_gs | indoor-real-estate | REAL | 411,066 | 123.9 MB | — | — | — | 59.5% +0.581 dB | — | — | — | 0 ms |
| bicycle_scaffold_gs | outdoor-scene | REAL | 912,445 | 275.0 MB | — | — | — | 59.5% +0.087 dB | — | — | — | 0 ms |
| garden_scaffold_gs | outdoor-scene | REAL | 745,121 | 224.6 MB | — | — | — | 59.5% +0.198 dB | — | — | — | 0 ms |
| stump_scaffold_gs | outdoor-scene | REAL | 746,258 | 202.1 MB | — | — | — | 66.2% +0.076 dB | — | — | — | 0 ms |
| treehill_scaffold_gs | outdoor-scene | REAL | 720,712 | 195.2 MB | — | — | — | 66.2% +0.056 dB | — | — | — | 0 ms |
| flowers_scaffold_gs | outdoor-scene | REAL | 705,051 | 191.0 MB | — | — | — | 66.2% +0.032 dB | — | — | — | 0 ms |
Try it on your splat
Drop a Gaussian-splat scene and we'll run the full upload → optimize → download round-trip against the hosted API live .