SPZ 4 is here: leaner, faster, and more future-proof
SPZ 4 is here: leaner, faster, and more future-proof
When we open-sourced SPZ in late 2024, we described it as "JPG for 3D Gaussian splats": a single, sensible format that made splats roughly 10x smaller than PLY and easy to share anywhere. Since then, Adobe Photoshop users alone have created roughly 800,000 SPZ files in the last two months. The format is now deployed across web environments, real-time engines, robotics pipelines, and mobile platforms – in scenes far larger and more complex than the original implementation was built for.
Today, we are releasing SPZ 4: an evolution of the format that preserves its core design principles while extending its capabilities to support significantly larger, more demanding datasets.
Previous versions of SPZ made it practical to share Gaussian splats directly from mobile devices, establishing a compact, portable format that enabled broad adoption. Subsequent releases focused on maturing the format: improving compression efficiency, stabilizing the specification, and expanding compatibility across rendering engines, web pipelines, and downstream systems.
SPZ 4 addresses the scale and complexity of current workloads, supporting captures with tens of millions of points and introducing a more robust data model where critical metadata is embedded within the file itself, rather than managed externally.
Bigger scenes, faster encoding
SPZ 4 compresses about 3-5x faster, loads roughly 1.5-2x faster end-to-end, still produces files that are 10x smaller than uncompressed PLYs, and gives developers new controls over the quality so the same format can serve both maximum-fidelity and maximum-efficiency workflows. The single biggest change in SPZ 4 is how the file gets compressed. The original SPZ wrapped the entire payload in a single GZip stream. That worked beautifully for the splats most people were producing in 2024 (a few hundred thousand points off a phone scan), but it meant compression and decompression were stuck on a single CPU core. Multi-million-point captures just take too long.
SPZ 4 replaces GZip with six parallel ZSTD streams, one per attribute (positions, colors, scales, rotations, alphas, spherical harmonics). Each attribute is its own independently-compressed buffer, with a small table of contents up front so the parser/loader can quickly determine the size and layout of each compressed attribute stream (positions, colors, etc.) without having to decompress or scan the file first. Encode and decode now scale across cores.
The result, from a benchmark on an 8.5 GB / 34M-point PLY:
|
Format |
Encode Time |
File Size vs. Baseline |
|
SPZ3 (baseline) |
3 min 26 sec |
- |
|
SPZ4 |
1 min 8 sec (3x faster) |
2.5% smaller |
You can get smaller files and much faster encoding, with full CPU utilization across cores. Decoding parallelizes the same way. We also removed the old 10-million-point cap on the PLY loader and on the SPZ deserializer. SPZ 4 happily handles tens of millions of gaussians without complaint.
The speedup shows up downstream too. Time-to-render (decompress plus load into the renderer) with parallel decoding drops noticeably (~33–52% faster, or roughly 1.5x to 2.1x) across our test scenes:
|
Benchmark Scene |
Points |
v2/v3 size |
v4 size |
TTR v2/v3 |
TTR v4 |
|
Scene A |
3.6M |
66.2MB |
65.7MB |
1,264ms |
844ms |
|
Scene B |
7.1M |
254MB |
128MB |
3,450ms |
1,660ms |
|
Scene C |
2.6M |
39.3MB |
40.5MB |
958ms |
619ms |
|
Scene D |
1.0M |
20.7MB |
18.9MB |
364ms |
238ms |
|
Scene E |
2.6M |
118.5MB |
65.1MB |
1,375ms |
657ms |
A plaintext header
SPZ 4 puts the 32-byte file header in plaintext at a fixed offset, outside the compressed region. That means you can inspect a file's point count, SH degree, version, and flags without decompressing a single byte of payload data.
Files now begin with the magic bytes NGSP rather than the original GZip magic. The loader sees the first four bytes and dispatches to the right path, so old SPZ v2/v3 files still load fine via a fallback path. Old loaders that encounter a v4 file fail fast with an unrecognized-format error rather than crashing or producing garbled splats.
A real extension system
The other big architectural change in SPZ 4 is extensions. The original format was deliberately rigid (one degree of compression, one parameter layout, no room to wiggle) because we wanted it to be a universal lowest common denominator. As SPZ use has expanded beyond its initial scope, that rigidity became limiting. SPZ 4 introduces controlled extensibility, allowing new attributes and metadata to evolve within the format without breaking interoperability.
The mechanism is an opt-in vendor extension chain. Each record carries a vendor-tagged ID, a length field, and a payload, which means unknown extensions can be safely skipped, and multiple vendors can coexist in the same file without stepping on each other. Extensions are disabled by default; you opt in via PackOptions. Files without extensions look identical to baseline SPZ, so older readers keep working.
The first extension comes from Adobe, who drove much of the architecture:
-
0xADBE0002 Safe Orbit Camera stores recommended elevation and radius bounds for orbit-style camera controls, so splat viewers don't have to guess how to frame and navigate the scene.
Vendor ID allocation is documented in extensions/README.md. We expect more extensions to follow; if you're thinking of adding one, the README is the place to start.
Better-looking splats, on your terms
SPZ 4 raises the ceiling on what splats can look like, and gives developers room to choose where on the quality curve they want to sit.
Configurable spherical harmonics quantization. The SH coefficients are what give a splat its view-dependent appearance: how light reflects off a surface, how a highlight moves as you orbit the camera, how much a material looks glossy versus matte. They're also one of the largest contributors to file size. You can tune the same scene for a maximum-fidelity archival render or a maximum-efficiency mobile viewer without reauthoring the splat. Internal testing showed an 18x compression ratio at 3 bits and essentially-zero MSE at 8 bits, with 5 bits being the sweet spot for most scenes.
Higher-fidelity splats with SH degree 4. Earlier SPZ versions topped out at SH degree 3, which covers most phone-captured splats but isn't enough for pipelines that produce more sharply view-dependent surfaces. SPZ 4 adds support for SH degree 4, so these higher-order splats round-trip through the format without losing the lighting detail they were generated with.
Together, these mean SPZ 4 is the first version of the SPZ format with a configurable quality dial.
SPZ at scale with Adobe
SPZ is increasingly the connective tissue for Gaussian splats across major creative and developer tools. Adobe has made SPZ central to its 3D toolchain – most recently shipping Photoshop's new Rotate Object feature, which lets users rotate 2D images in 3D space and gained traction immediately at launch. SPZ is the transacting format behind this capability, putting it in the path of millions of users.
Faster on the web and a growing ecosystem
A lot of SPZ usage now happens in the browser, through our Emscripten/WASM build. Alongside the SPZ 4 format release, the reference library ships a rebuilt WASM/TypeScript binding layer with proper TypedArray views over the gaussian data, plus a generated spz.d.ts for editor autocomplete. Loading SPZ files in the browser is also up to 20x faster. SPZ 4 adds Emscripten bindings for the C++ to JavaScript layer, delivering meaningful performance gains for web-based workflows.
The web ecosystem around SPZ is also expanding. Adobe recently extended SPZ support in Babylon.js, making it easier to load and render SPZ assets directly in web-based 3D pipelines.
A web tool for inspecting and converting splats
Alongside the library release, we're shipping a small WASM-powered web tool for working with splat files at nianticspatial.com/spz-converter. Drop a .spz or .ply file onto the page and it shows you the header, point count, SH degree, stream layout, and bounding box, then lets you convert between formats or export the metadata as JSON. Everything runs locally in the browser.
Backwards compatibility
A quick summary of what reads what:
-
SPZ 4 reads everything. Old SPZ v2/v3 files load fine via the legacy path.
-
Old loaders cannot read SPZ 4 files. They'll see the new NGSP magic and fail gracefully by reporting an unrecognized format.
-
Files without extensions appear as standard SPZ to loaders that do not implement or recognize extensions.
Breaking forward-compat with old readers is not a decision we make lightly. But the encoding speedups, the parallel decoding, the plaintext header, and the room to grow added up to a clear yes.
What's next
The architectural changes in v4 unlock future improvements. A few of the directions on our radar for v5:
-
Streaming and progressive loading.
-
Better SH quantization.
-
Spatial chunking and LOD.
-
More vendor extensions.
If you have ideas you'd like to see explored, please open an issue on the repo to start a discussion, or send a pull request if you've already prototyped something. The best parts of SPZ have come from people pushing on it from the community.
Get started with SPZ 4
There are a few easy ways in, depending on what you're trying to do:
If you just want to compress a PLY or look inside an SPZ file, head to nianticspatial.com/spz-converter and drop a file onto the page. No install, no signup, no upload. You'll get a header readout in seconds, and one-click conversion between .ply and .spz v4.
Drop a file here or click to browse
We'll detect the format and show the right actions.
No file loaded
Drop a splat file on the left to inspect its properties and convert it.
If you want to integrate SPZ into your app, the library is on GitHub at github.com/nianticlabs/spz. For C++ projects, clone the repo and link against the core library. For Python, pip install from the repo gives you the bindings. For the web, the WASM build with TypeScript definitions is also there. For most existing integrations SPZ 4 is a drop-in upgrade: pull main, and your existing load/save calls keep working, with writes now producing v4 by default.
We'll be adding SPZ 4 exports to Scaniverse within a few months. We encourage anyone developing an app that imports SPZ to join us in this timeline so we can advance together.
If you want to contribute code, we welcome pull requests. Bug fixes and platform-specific build improvements are quickly incorporated; for larger changes (new extensions, format-level tweaks, performance work) please open an issue first to talk through the design. The extensions/README.md file documents the vendor ID allocation scheme if you're thinking of adding your own extension. Good first PRs include build improvements, integration guides for popular renderers, and tooling around the web utility.
A big thank you to everyone who made this release happen, especially the team at Adobe, who drove the extension architecture and a great deal of the WASM work, and to the community members who filed issues, ran benchmarks, pushed back on early designs, and provided the feedback that allows us to build better together. SPZ has always been better when more people are looking at it.
If you've been waiting to put bigger scenes, faster web viewers, or your own metadata into SPZ, go pull the latest. We can't wait to see what you build.