Encode a scene in Python
The Python package is the reference implementation — the one the conformance corpus is generated from, optimized for being obviously correct. See the feature matrix for what is implemented today.
pip install fourdgs
A scene is a GaussianSet and a duration
Gaussians are held structure-of-arrays, one NumPy array per attribute. Every array is float32 and
n rows long; rotations are xyzw, colors are red, green, blue and alpha, and motions are
units per second.
import fourdgs
gaussians = fourdgs.GaussianSet(
positions=positions, # (n, 3)
scales=scales, # (n, 3), linear
rotations=rotations, # (n, 4), xyzw, normalized
colors=colors, # (n, 4), red, green, blue, alpha
motions=motions, # (n, 3), units per second
mu_t=mu_t, # (n,) birth time
sigma_t=sigma_t, # (n,) temporal extent; inf means "never fades"
win_lo=win_lo, # (n,) validity window start
win_hi=win_hi, # (n,) validity window end
)
fourdgs.write("scene.4dgs", gaussians, 8.0)
sigma_t may hold inf, meaning the gaussian never fades inside its window. That is a value rather
than a sentinel: it survives encode and decode as infinity, and readers expose it as such.
write takes a path or any file-like object and returns the number of bytes written. An
AudioTrack and a CameraTrajectory are optional keyword arguments; a scene without them carries
nothing at all for them.
A complete, runnable version of the above — including generating the arrays — is
python/examples/encode_synthetic.py,
which CI runs so it cannot rot into a snippet that no longer works.
Options
WriteOptions carries the encoder's decisions. The defaults produce an indexed, CRC-checked,
deflate-compressed file at the default quantization profile.
options = fourdgs.WriteOptions(
profile="default", # "fine" | "default" | "coarse"
min_chunk_gaussians=2048, # chunk granularity, together with max_depth
write_index=True, # the chunk index; without it a reader must stream
write_crc=True,
sh_bands=3,
)
fourdgs.write("scene.4dgs", gaussians, 8.0, options=options)
Two of these are worth understanding rather than accepting.
cutoff is the Header's marginal visibility threshold, and it is not only metadata: it sets the
support constant the per-gaussian velocity grid is derived from, so encoder and decoder must agree
on it — and they do, by reading it from the file.
verify is on by default. The encoder decodes back what it just wrote and refuses to return a
file whose measured deviation exceeds the bounds that file is about to declare. A declared bound
nobody checked is worse than no bound, because consumers will trust it.
From a PLY sequence
A directory of per-frame gaussian splat PLY files, in name order, converts directly:
4dgs convert frames/ -o scene.4dgs --fps 30 --profile default
The same conversion is available as fourdgs.convert.convert_ply_sequence(directory, fps=30.0),
which returns the GaussianSet and the duration for you to write yourself.
Checking the result
4dgs info scene.4dgs # summarize the file and what seeking it costs
4dgs validate scene.4dgs # check it against the specification
4dgs decode scene.4dgs -t 2.5
The specification is the normative reference for everything above, and concepts is the one-page vocabulary.