Python 3 tools for Insta360 consumer cameras (built around Insta360 X5, same Wi‑Fi OSC pattern as X3 / X4 / X5-class models): talk to the camera at http://192.168.42.1 using the Open Spherical Camera (OSC) HTTP API (Google OSC / Street View spherical camera reference; Insta360’s OSC notes), download a stitched equirectangular 360° panorama ( photoStitching: ondevice ), and browse / view it locally with Flask + Pannellum.
insta360_shoot_360.py—GET /osc/info,camera.getOptions/camera.setOptions,camera.takePicture, status polling, chunked download tophotos_360/.viewer_app.py— Small Flask web UI to pick files and view equirectangular images in the browser.
Search-friendly terms this repo matches: Insta360 OSC, Insta360 Python, Wi‑Fi panorama download, Google Open Spherical Camera, /osc/commands/execute, 360 photo stitching, Pannellum, 192.168.42.1.
There is no mobile app dependency at runtime beyond one‑time camera activation in the official Insta360 app if the camera reports unactivated.
| Piece | Role |
|---|---|
insta360_shoot_360.py |
GET /osc/info, camera.getOptions / camera.setOptions (captureMode: image, photoStitching: ondevice), camera.takePicture, poll status, stream download to photos_360/. |
viewer_app.py + templates/viewer.html |
Lists photos_360/, serves images safely, embeds Pannellum from a CDN. |
viewer_360.html |
Optional static single‑file viewer (handy with python -m http.server); the Flask app replaces most of that workflow. |
Why photoStitching: ondevice?
Without it, many Insta360 bodies return unstitched dual‑fisheye (e.g. .insp / unstitched JPG). With ondevice, the camera produces a stitched equirectangular JPG with metadata suitable for 360 viewers (Pannellum, Google Photos, etc.).
- Python 3.10+ (type syntax
str | None,Path | None, etc.) - Insta360 camera with consumer Wi‑Fi OSC (e.g. X5); default base URL is
http://192.168.42.1when the PC/phone is joined to the camera’s access point (SSID likeInsta360 X5 XXXX.OSC). requestsfor the capture script;flaskfor the viewer.
Install everything:
pip install -r requirements.txtOr install only what you need:
pip install requests # capture only
pip install -r requirements-viewer.txt # viewer only (Flask)- Power on the Insta360 X5.
- On your computer, join the camera Wi‑Fi network (e.g.
Insta360 X5 …OSC). - Ensure the camera is awake, on photo / 360 still mode (not playback-only sleep), and not held by another OSC client (e.g. close Insta360 app remote if it blocks OSC).
- If you have never activated the camera, do that once in the official Insta360 app (the script surfaces
unactivatedclearly).
From the repository root:
python3 insta360_shoot_360.py- Saves files under
photos_360/(created if missing). - No CLI arguments — one run = one capture + download.
- Exit codes:
1unreachable camera,2OSC error,3capture timeout,4other HTTP errors.
python3 viewer_app.pyOpen http://127.0.0.1:8765/ (or from another machine on your LAN: http://<this-pc-ip>:8765/ — the app listens on 0.0.0.0).
- Sidebar lists images in
photos_360/(newest first), with a name filter and Refresh. - Click a row to load it in the 360 viewer.
- Deep link:
http://127.0.0.1:8765/?image=IMG_….jpg
Security note on shared networks: the viewer is meant for local / trusted LAN use. It serves every allowed image under photos_360/ to anyone who can reach the port. For untrusted networks, bind to 127.0.0.1 only (change app.run in viewer_app.py) or put HTTPS + auth in front (reverse proxy).
.
├── README.md # This file
├── requirements.txt # requests + flask
├── requirements-viewer.txt # flask only (optional split)
├── insta360_shoot_360.py # OSC capture → photos_360/
├── viewer_app.py # Flask entrypoint
├── viewer_360.html # Optional static CDN viewer
├── templates/
│ └── viewer.html # Flask UI + Pannellum
└── photos_360/ # Output & viewer source
| Constant / behavior | Default |
|---|---|
| Camera base URL | http://192.168.42.1 |
| Output directory | ./photos_360/ |
| HTTP timeouts | Connect 5s, read 30s; capture poll up to 90s (stitching can be slow) |
To use another host or path, edit the module‑level constants at the top of insta360_shoot_360.py (or fork and add env vars / CLI if you extend it).
| Symptom | Things to try |
|---|---|
Cannot reach /osc/info |
Wrong Wi‑Fi — join the camera AP, not only phone tethering to the same name. |
unactivated |
Open the official Insta360 app once and complete activation / pairing. |
disabledCommand |
Wake camera (power/shutter), switch UI to 360 / still photo, disconnect other OSC clients; script already waits after /osc/state, primes captureMode, and retries some steps. |
invalidParameterName / HTTP 400 on getOptions |
Firmware may reject unknown option names; the script uses tiered getOptions and documented names first. |
| Viewer shows empty list | Run the capture script once, or point PHOTOS_DIR in viewer_app.py at your folder. |
| Browser 360 is black / WebGL errors | Use the Flask URL (http://127.0.0.1:8765/); avoid file:// for WebGL panoramas. |
- Insta360 OSC (GitHub) — headers,
getOptions/setOptions,takePicture, stitching notes. - Google Open Spherical Camera API — protocol background.
- Pannellum — browser equirectangular viewer (loaded from CDN in this project).
This project is not affiliated with Insta360. Camera behavior depends on firmware; OSC options and error strings can change. Test on your own hardware before relying on it in the field.
This project is licensed under the GNU General Public License v3.0 — see LICENSE.