Skip to main content

mirame360-spatial-metadata

CLI tool to inspect and inject spherical metadata into 360° photos and videos.

The Problem

360° photos and videos need specific embedded metadata to be recognized as spherical (not flat/distorted) by viewers like YouTube, Facebook, and web browsers. Cameras and editing tools frequently strip this metadata, leaving creators confused about why their 360° content looks broken or displays as a warped flat image.

mirame360-metadata fixes this — it lets you inspect whether your files have the right metadata, and inject it if they don't.

Features

  • inspect — Check whether a photo or video has valid spherical metadata, and show what's present or missing
  • inject-image — Write Google Photo Sphere XMP (GPano) tags into JPEG or PNG images without discarding existing XMP
  • inject-video — Write Spherical Video V2 metadata (sv3d box) into MP4/MOV files

Installation

Image inspection and injection require ExifTool, a system application (not a Python package). Install it first:

# macOS
brew install exiftool

# Debian / Ubuntu
sudo apt install libimage-exiftool-perl

# Windows
winget install OliverBetz.ExifTool

Confirm that exiftool -ver works, then install the Python package:

git clone https://github.com/mirame360/mirame360-spatial-metadata.git
cd mirame360-spatial-metadata
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Usage

Inspect a file

# Check if a photo has spherical metadata
mirame360-metadata inspect my_photo.jpg

# Check if a video has spherical metadata
mirame360-metadata inspect my_video.mp4

Example output for a photo with metadata:

Found GPano metadata in my_photo.jpg:
  GPano:ProjectionType = equirectangular
  GPano:CroppedAreaImageWidthPixels = 4000
  GPano:CroppedAreaImageHeightPixels = 2000
  GPano:FullPanoWidthPixels = 4000
  GPano:FullPanoHeightPixels = 2000
  GPano:CroppedAreaLeftPixels = 0
  GPano:CroppedAreaTopPixels = 0

Inject image metadata

# Write GPano XMP tags to a JPEG or PNG (saves to a new file)
mirame360-metadata inject-image my_photo.jpg --output my_photo_360.jpg

# Modify in-place (no --output flag)
mirame360-metadata inject-image my_photo.jpg

# Describe a 2000x1000 partial image cropped from a 4000x2000 full sphere
mirame360-metadata inject-image partial.jpg \
  --width 4000 --height 2000 --left 1000 --top 500 \
  --output partial_360.jpg

The tool always reads the cropped-area width and height from the actual image. --width and --height describe the uncropped full sphere; omit them for a normal, uncropped panorama. --left and --top locate a partial image within that full sphere and default to zero. The crop must fit inside the declared full dimensions.

If the full panorama's aspect ratio is not approximately 2:1, the tool warns but still proceeds.

Inject video metadata

# Write sv3d box to an MP4
mirame360-metadata inject-video my_video.mp4 --output my_video_360.mp4

# Without --output, creates my_video_spherical.mp4 automatically
mirame360-metadata inject-video my_video.mp4

How It Works

Images: GPano XMP

360° images use Google's Photo Sphere XMP Metadata standard. The required tags use the GPano namespace (http://ns.google.com/photos/1.0/panorama/). The tool delegates XMP reading and writing to ExifTool, which supports both JPEG and PNG and updates only the requested GPano properties, preserving unrelated XMP such as titles, ratings, keywords, and copyright.

Videos: Spherical Video V2

360° videos use the Spherical Video V2 RFC standard. Metadata is stored as an sv3d box inside the MP4 container's video track, containing a spherical video header (svhd), a projection box (proj) with projection header (prhd) and an equirectangular projection box (equi). This is the format recognized by YouTube, Facebook, and other major platforms.

The vendored Google implementation modifies only the first video track. Files with multiple video tracks should be split or handled separately so this limitation is not mistaken for metadata on every track. Injection also requires a sample-entry codec supported by the vendored implementation; unsupported entries fail explicitly.

Credits

Video metadata injection uses vendored code from Google's spatial-media project (Apache-2.0 licensed). This is the official reference implementation of the Spherical Video V2 specification, and we use its own parser to verify that injected metadata is valid.

License

This project is licensed under the GNU General Public License v3.0 (GPLv3).

GPLv3 was chosen specifically because it is compatible with the Apache-2.0 license of the vendored spatial-media dependency — Apache-2.0 licensed code can be included in GPLv3 projects (but not the other way around).

See LICENSE for the full text.


Built by Mirame360 — Free 360° photo and video hosting

Release files for mirame360-metadata 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mirame360-metadata 0.1.0
File Size Uploaded
mirame360_metadata-0.1.0.tar.gz 52.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mirame360-metadata 0.1.0
File Interpreter ABI Platform
mirame360_metadata-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 114.8 kB

Release files / mirame360_metadata-0.1.0.tar.gz

Download URL mirame360_metadata-0.1.0.tar.gz
Size 52.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d70368244ec0604508f2574eac43ee2b743ad7b2f6c2f8851d9ee7aefac2d9ae
BLAKE2b-256 checksum
How to use checksums
523e5462b7cbebd1187ad91a49770db60abe3d39f4871074deb46d358c39acb5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release files / mirame360_metadata-0.1.0-py3-none-any.whl

Download URL mirame360_metadata-0.1.0-py3-none-any.whl
Size 61.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
295b5a757637f191ab345ba09b0066ea62b74cad7ca5af3b33510f69cc41558e
BLAKE2b-256 checksum
How to use checksums
38ec9b86ffe819ad23e532263cbdfcf851616764d4f4ea6cf50f5b40d34cdaf0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page