Skip to content
Open specificationApache-2.0macOS · Linux · Windows

Any rig, any dataset. Converted once.

There is no standard for what a capture arrives as. glTF, SPZ and the MPEG codecs describe what comes out of a reconstruction; the gap is on the input side, and every rig, phone and research dataset expresses poses, time, depth and scale differently. The VoxaVerse Capture Package is our candidate for closing it — and it is public, in full, with the tools that read and write it.

Why it exists

The failures are not loud.

That is the whole argument for declaring rather than inferring.

A camera convention read one way instead of another produces a reconstruction that renders perfectly and is inside-out.

Millimetres read as metres misplace every surface by a factor of a thousand — and validate fine.

Structure-from-motion output silently mixed with LiDAR corrupts every measurement downstream.

The toolchain

Three verbs.

Local-only. No telemetry, no network calls.

vvspec convert  ~/scans/my_model  out.vvspec   # from COLMAP, Nerfstudio, LLFF, …
vvspec validate out.vvspec                     # is it well-formed?
vvspec verify   out.vvspec                     # …and unaltered since export?
convert

Read a capture in someone else’s convention and write it out in one that states what it is. The source format is detected; --dry-run answers how big and how long before you find out the slow way, and --resume continues an interrupted run by digest rather than by timestamp.

validate

Check a package against the schema, the frame tables and every file it references. Every refusal carries a stable code, a sentence written for the person holding the folder, and a machine-readable locator.

verify

Everything validate does, plus recompute every recorded digest — the difference between “well-formed” and “unaltered since it was exported”.

Exit codes are part of the interface: 0 valid, 1 refused with a code, 2 the command line was wrong and nothing was read. The validator embeds in Rust or in Swift, and both run the same conformance vectors.

Adapters

Formats it already speaks

Each one written against the format owner's own documentation, with the axis test written first.

SourceWhat the adapter handles
COLMAPSparse model, text — per-image poses from images.txt
Nerfstudiotransforms.json, shared or per-frame intrinsics
LLFFposes_bounds.npy, including the axis-permutation trap, with a test for it
PolycamARKit keyframes with metric LiDAR depth
TUM RGB-DA real recorded clock, at exact nanosecond timestamps
Blender / D-NeRFSynthetic captures, including D-NeRF’s normalised time

A migrator carries packages written before the format settled. Writing a seventh adapter starts with a checklist of the facts you must find in the format owner’s documentation before writing any code — and a held-out test harness that removes one existing adapter and scores a candidate against a golden round trip it never sees.

Design commitments

What it promises, and what it refuses.

Declare everything. Guess nothing.

Axes, handedness, quaternion order, pose direction, units, depth encoding and alignment, whether the scale means anything, and whether the timestamps were recorded or synthesised are all required, declared fields. A package states what it contains; a reader obeys the statement rather than inferring one.

Hostile input is expected.

A capture package is a file a stranger sent you. Bounds are checked before anything is allocated from a count the file itself declared, and a seeded mutation harness runs tens of thousands of rounds against the parsers on every build. The threat model is written down.

Bounded memory, measured.

Validation cost does not grow with the capture: one fixed read buffer, not a fraction of the dataset. Frames ride inline for small captures and as streamable per-node tables for large ones — a six-camera ten-minute shoot is around a hundred thousand frame records, and a format that forces those into one JSON array has not met a real capture.

Byte-stable output.

Same input, same bytes — no clock, no randomness, sorted keys, canonical quaternion sign. That is what makes a package hashable, diffable and cacheable instead of merely readable.

The refusals are the interesting part.

One well-known phone format is deliberately absent, because its depth units and camera axis convention could not be established anywhere authoritative — and those are exactly the two facts a wrong adapter gets silently wrong. It ships the day either is settled.

Two implementations, one suite.

A Rust validator and a Swift validator share no code and run the same conformance vectors, producing the same codes. That agreement is the parity proof, and it is what makes the vectors — not the prose — the standard.

Licence

Vendor it. Don't retype it.

A retyped schema is a divergent schema, so the pieces you would need to copy are licensed for copying.

WhatLicence
Code — validator, converters, CLIApache-2.0
Specification textCC BY 4.0
Schema and conformance vectorsApache-2.0 OR MIT

This is offered as a candidate, not declared a standard — adoption decides that, not a README. The format is settled at its first major version; the tooling is versioned separately and reaches its own first major once it has met more rigs than ours. Fixtures are synthetic or our own, and an audit enforces that even for datasets whose licences would permit vendoring. If you find a security issue, the repository states how to report it privately; anything else is welcome at support@voxaverse.ai.

Bring your own rig.

Convert a capture once and it imports into the studio with the same certainty as one of ours — and the scene that comes out opens in the viewer on this site.

Building a capture rig of your own? The calibration page has the target generator and the field planner.