CLI Guide
Inspect and inject spherical video and spatial audio metadata into MP4 and MOV files.
Supports v1 (XML in a UUID box) and v2 (native SV3D / ST3D atoms).
On inject, conflicting v1/v2 tags are cleared so players see a single coherent
metadata set.
Install
Recommended: download a standalone binary from GitHub
Releases. Make it executable, then run spatialtag -h.
Or install from a git clone:
git clone https://github.com/Nandan-18/spatialtag.git
cd spatialtag
python3 -m pip install -e .
spatialtag -h
Examine
Print spatial media metadata for each file:
spatialtag video.mp4
spatialtag clip1.mp4 clip2.mov
Inject
Write metadata to a separate output file:
spatialtag -i [options] <input> <output>
Common examples:
# Mono 360 equirectangular (v1)
spatialtag -i input.mp4 output.mp4
# Stereoscopic left-right (v1)
spatialtag -i --stereo=left-right input.mp4 output.mp4
# v2 atom metadata
spatialtag -i -2 --stereo=left-right input.mp4 output.mp4
# v2 with VR180 equirect bounds (fixed-point crop on each border)
spatialtag -i -2 --stereo=left-right \
--bounds="0:0:0x40000000:0x40000000" input.mp4 output.mp4
# v1 crop region (w:h:full_w:full_h:left:top)
spatialtag -i --stereo=left-right \
--crop="4096:4096:8192:4096:2048:0" input.mp4 output.mp4
# Spatial audio (first-order ambisonics, ACN + SN3D)
spatialtag -i -a input.mp4 output.mp4
You can also pass the same path twice with -i to request in-place output when
supported:
spatialtag -i --stereo=left-right video.mp4 video.mp4
In-place inject
Rewrite metadata without a full second copy of the media. Prefer -I for a
single file:
spatialtag -I --stereo=left-right video.mp4
Requirements: the file layout must allow updating moov without shifting
mdat offsets. This is typical when moov comes after mdat (common for
files optimized for streaming). If moov is before mdat, in-place inject is
refused; use separate input and output paths.
VR180 helper
For side-by-side equirectangular VR180, --vr180 reads the video track
dimensions and sets left-right stereo, v1 crop, and v2 180° bounds
automatically:
spatialtag -I --vr180 video.mp4
Example: an 8192×4096 SBS frame gets half-width eye crop and 0x40000000 (90°)
bounds on left and right.
CLI reference
Modes
| Flag | Description |
|---|---|
| (default) | Print metadata for each file |
-i, --inject |
Write metadata to <input> → <output> |
-I, --in-place |
Inject into a single file in place |
Spherical video
| Flag | Values | Default | Description |
|---|---|---|---|
-2, --v2 |
flag | off | Use v2 box metadata instead of v1 XML |
-s, --stereo |
none, top-bottom, left-right |
none |
Stereoscopic layout (RFC) |
-p, --projection |
none, equirectangular |
equirectangular |
Projection type |
-c, --crop |
w:h:f_w:f_h:x:y |
(none) | v1 crop region (six integers) |
-b, --bounds |
top:bottom:left:right |
(none) | v2 equirect bounds (four 0.32 fixed-point values) |
--vr180 |
flag | off | Derive VR180 stereo + crop/bounds from video size (implies v2 fields) |
Spatial audio
| Flag | Description |
|---|---|
-a, --spatial-audio |
Inject spatial audio metadata. Input must contain a supported first-order ambisonics track (ACN channel order, SN3D normalization). See the Spatial Audio RFC. |
Desktop GUI
Requires the gui extra when installing from source:
python3 -m pip install -e ".[gui]"
python3 -m spatial.gui
The GUI supports spherical video, stereoscopic modes (none / left-right / top-bottom), and spatial audio when the file has a compatible ambisonics track.
For large files or headless servers, use the Docker web UI, the
browser demo, or the CLI with -I.
Standalone executables
Install build dependencies, then choose the CLI or GUI PyInstaller spec:
python3 -m pip install -e ".[build]"
# Console CLI binary (spatialtag)
pyinstaller --clean --noconfirm spatial/spatial.spec
# Desktop GUI (SpatialTag / SpatialTag.app)
python3 tools/build.py
# or: pyinstaller --clean --noconfirm spatial/gui.spec
The GUI bundle is built from spatial/gui.py (Tkinter). On Linux you may need
python3-tk installed separately. Release CI publishes CLI binaries; build the
GUI locally when you need a desktop app.
Programmatic use
The injector is importable as a library:
import spatial.metadata as meta
meta.parse_metadata("video.mp4", print)
md = meta.Metadata("equirectangular", "left-right", None)
md.video = meta.generate_spherical_xml("equirectangular", "left-right")
meta.inject_metadata("input.mp4", "output.mp4", md, print)
Lower-level MP4 box helpers live under spatial.mpeg.