Photo Spot
Turn one photo into a 13–16 second vertical "where was this taken" reveal video: a satellite globe dive to the camera spot and the photographed place, a camera pin and a subject pin
- What
- Turn one photo into a 13–16 second vertical "where was this taken" reveal video: a satellite globe dive to the camera spot and the photographed place, a camera pin and a subject pin
- Cost
- Free
- Needs
- Before you start: read this whole install prompt, tell me in a few lines what this skill does and what installing it involves, and wait for my go-ahead before you do anything else.
- Install
- Copy the installer prompt below into your Muse — your agent does the rest.
Curated by Skill Harbor — Turn one photo into a 13–16 second vertical "where was this taken" reveal video: a satellite globe dive to the camera spot and the photographed place, a camera pin and a subject pin, a viewfinder fan sweeping between them, a focus frame locking green, a shutter click, then the photo flipping up in 3D from the camera spot over its own blurred background — with an optional iPhone Live Photo effect (still simulation or the real MOV). Reads the photo's EXIF GPS/direction/settings locally, finds places through Amap POI search, and renders through the map-motion engine bundled in the same repository. By @SpaceZephyr, listed here with credit to its creator. MIT-licensed. Skill Harbor never reviews the code, review it yourself before use.
Version:
Install
Copy the install package below, then paste it into Muse📌 Pinned version: commit 65ab781The install prompt below already includes the vetting steps: your agent follows the community checklist before installing anything with executable code. Want more?
- It can run commands on your Muse’s computer.
- It can contact outside services over the network.
- It can create or modify files.
- It works with an API key or a token that you provide.
What the scan found — excerpts from the install prompt
- runs commands — Prerequisites: the install itself is only a file copy (no account, no key, no script run), but using the skill · - What leaves this machine at use time, disclosed here before it ever happens — using the skill is a separate
- makes network calls — - What leaves this machine at use time, disclosed here before it ever happens — using the skill is a separate · - Ce qui quitte cette machine à l'usage, divulgué ici avant que ça arrive — utiliser le skill est une étape sé
- writes files — Prerequisites: the install itself is only a file copy (no account, no key, no script run), but using the skill · - What leaves this machine at use time, disclosed here before it ever happens — using the skill is a separate · Prérequis : l'installation elle-même n'est qu'une copie de fichiers (aucun compte, aucune clé, aucun script ex
- uses API keys or tokens — Prerequisites: the install itself is only a file copy (no account, no key, no script run), but using the skill · Prérequis : l'installation elle-même n'est qu'une copie de fichiers (aucun compte, aucune clé, aucun script ex
Before you start: read this whole install prompt, tell me in a few lines what this skill does and what installing it involves, and wait for my go-ahead before you do anything else. Prerequisites: the install itself is only a file copy (no account, no key, no script run), but using the skill needs setup that is NOT part of this install, so read it before you decide: (1) a free Amap (Gaode) Web Service API key of my own — the documented flow searches Amap POIs and geocodes place names with it (spot.sh find, and name-based places at compile time); it is read from the environment variable AMAP_KEY or from ~/.config/map-motion/amap_key, never written into a spec or a project folder. I get the key myself from the Amap open platform; it is free within its daily quota. (2) The uv tool and ffmpeg on my machine. (3) On first use only, the bundled shell wrappers run Python through `uv run --with ...`, which downloads Python packages from PyPI (certifi, pillow, pillow-heif for the photo-spot helper; certifi and pillow for the compiler; playwright and certifi for the renderer), and the renderer needs a headless Chromium downloaded once through Playwright (`playwright install chromium`). None of that is installed by this install. I also provide the photo myself: the skill reads its EXIF (GPS position, direction, camera settings) when the original file still has it — a photo pasted in chat, a screenshot, or one sent through a messaging app has usually been stripped of EXIF, and then the location has to be guessed from the picture and confirmed by me before anything is rendered. Install "photo-spot" for me. It turns one photo into a 13–16 second vertical (portrait) short video that reveals where the photo was taken: a satellite globe dive down to the camera spot and the photographed place, a camera icon and a pin dropping in, a viewfinder fan sweeping from the camera to the subject, a focus frame that locks green, a shutter click (synthesised shutter sound), then the photo itself flipping up in 3D perspective from the camera spot against a blurred version of itself, handwritten caption and coordinates below; optionally an iPhone Live Photo effect (a still-photo simulation, or the real MOV — first 3 seconds with its original sound). It is a sub-skill of the map-motion rendering engine in the same repository: photo-spot manages the flow (read EXIF → pin down both locations → write a "snap" spec → still-frame check → render), and the map-motion engine at the repository root does the compiling and rendering. That is why the install below copies files from two places in the same pinned commit. Repository: https://github.com/SpaceZephyr/map-motion (the skill is the photo-spot/ folder, 7 files, PLUS the map-motion engine files it strictly needs at the repository root, 21 files — 28 files in total, all listed with fingerprints in point 1) Pinned version: install the code at commit 65ab781832cace6e0f28d4c00452410a99f3a02c exactly. Do not substitute a newer version. If this commit is unreachable, stop and tell me. 1. Clone https://github.com/SpaceZephyr/map-motion into a temporary folder, check out commit 65ab781832cace6e0f28d4c00452410a99f3a02c, and copy only these 28 files from that checkout, keeping their repository-relative layout. Then compare every copied file with the fingerprints recorded for this listing on 2026-10-19: [FINGERPRINTS] - photo-spot/SKILL.md: SHA-256 559fe6829e555fc4600141f81c1d5ca783a7c960e0a3c8f3bd3604055d36ae02 - photo-spot/scripts/spot.py: SHA-256 0b5197983bdfc601e11e93ecc1473a0d8f40c6637ba5617594f83e758bff7cad - photo-spot/scripts/spot.sh: SHA-256 e937ccac2909a214dd90787c37c7589b8a9ad49a80c22d912b2530959d6fd4af - photo-spot/examples/README.md: SHA-256 f4564e9260f24bbd73b97677af51dcf489ed5429ca1d6136e668209f987bc2cc - photo-spot/examples/fuji_shinkansen.json: SHA-256 1b903cf7cde66bf1bf9c450c63d91372df91bb56711d7575a54125158f378b35 - photo-spot/examples/high_junk_peak_live.json: SHA-256 727153ead06d29d5fd4e3fdc594106939b45b16ea7e5490253a8a4765c40dbae - photo-spot/examples/yubeng_waterfall_live.json: SHA-256 e948ca5ae467077f8e6f3806b6248a09deae14632fa2185ec5378c86dc747a13 - SKILL.md: SHA-256 d3848172be1eca9b4cd8ba3e51a76bb5ff5a8e39b8d421a357e0b5e12f159790 - LICENSE: SHA-256 503807b77b7096091e3be3fdec62cfdc41f7de2a1b805a05e586edae7a7a657c - scripts/make.sh: SHA-256 9fc63a0c7933448d46b28b7352d233d88d251399205d6d52015f868cb21c49af - scripts/compile.py: SHA-256 32420d87aa526d5bf86ea526dfb61e63d4ba2b31666c5828bbb4d5bbd3a5879e - scripts/amap.py: SHA-256 7db7efbaf5b63362ca8078d88da9f0606e5c38a92410c3643e0f19072486b92d - scripts/osm.py: SHA-256 3e30d7b0d8288f5a62de626f428899cddf9c7ca5b3e94623ebf7892a307421e2 - scripts/elev.py: SHA-256 ec41a716692742c58a80596b1df804db02d8f7017108ad2d0797b2b1b5b588a7 - scripts/render.py: SHA-256 fd5eb323b0207c9b9920aa6dc24982113a04020b582fe67266f8359a57db5ecd - scripts/qa.py: SHA-256 9b87b89c690d22aeecf0441685f2d7489a2379cf9a8c9514045e2438eeb19baa - scripts/audio.py: SHA-256 4785e478cea1ff36158f3db471214706465fa7cd8946e516c5f4faad6d52770e - scripts/runtime/index.html: SHA-256 898c81ea79e2828b5fb6d37c80c0ca1fe9048640ab78523d4670a0749cedd34d - scripts/runtime/mm.js: SHA-256 f943260dea924193a67eb6df587b04053a16f844ed0d930fab35def86bbf31f3 - scripts/runtime/qa.js: SHA-256 8c761421f289a378b8341fac965a1f516567899eda9cb5786ac1fc8f792e801a - assets/china.json: SHA-256 df6c10e3d0be10052355a958812a5decd60a544b858b2934b170ca0fdebf2985 - assets/land.json: SHA-256 e8546a66c5ad7545d60097580fd8abd154c6257ae4b5022ff2dfadc62fc4ce46 - assets/fonts/Anton-400.woff: SHA-256 791375bdbed00de4a3aad4811291220ead0e1405d6f8b5bdbf109798c8359ac5 - assets/fonts/LXGWWenKai-500.woff: SHA-256 734bd187392579417ac83effe31d37b9de43c7b290bcb400800456511ed79e8f - assets/fonts/NotoSansSC-700.woff: SHA-256 dd0d39a9780eb995c499af0c20cca93b1dfdda865da70871a20890b3e406b968 - assets/fonts/NotoSansSC-900.woff: SHA-256 d2d8a42438b18b65b6577434df4e41bb08c6b5051281757849af00ab743bb58f - references/spec.md: SHA-256 14d38fb1e8185922b2f3ac5f581ac966b5255f9cc3fced69ed22fbcd91e3ab57 - references/amap.md: SHA-256 2c2e6b441b2fdd5361a10c9a58c44f5b6ecc39a880ba43a1d2a8bca841d0a85d If a file does not match, it changed since the listing was prepared: do not install it yet, tell me what you found and let me decide. 2. Read photo-spot/SKILL.md and the engine SKILL.md in full, read photo-spot/scripts/spot.py and spot.sh, and read the engine scripts that photo-spot actually runs (scripts/make.sh, scripts/compile.py, scripts/amap.py, scripts/render.py, scripts/qa.py, scripts/audio.py, scripts/runtime/mm.js and qa.js), and tell me in plain words: what the skill does when used, which services it connects to, whether it reads or sends any personal information or keys, and anything that seems unusual. Stop on any red flag and tell me before going further. Confirm these points from the files: - The install perimeter is 28 files and nothing else in the repository is needed by photo-spot: the photo-spot/ folder is complete in itself (SKILL.md, its helper spot.py/spot.sh, and three example specs), and spot.py finds the engine in exactly two ways — an installed ~/.claude/skills/map-motion/scripts folder first, or, when run inside a repository checkout, the scripts/ folder two levels up. The engine files copied here are exactly the ones the snap flow loads: make.sh runs compile.py (which imports amap.py, osm.py and elev.py at startup, so all three must be present even though the snap shot itself only calls amap.py) and then render.py (which imports qa.py and audio.py, and serves scripts/runtime/index.html with mm.js and qa.js; mm.js always loads assets/land.json, assets/china.json and the four .woff fonts). references/spec.md and references/amap.md are the engine documentation the two SKILL.md files point to (spec format, Amap key setup). NOT copied, and not needed for photo-spot: the sibling skills map-3d/ and travel-vlog/ (separate listings), the 3D/sun engine modules (scripts/geo.py, dem.py, sun.py, sunlight.py, terrain3d.py, scripts/runtime/t3d.js, terrain.html, hud.js), scripts/status.py (an optional progress viewer), assets/examples/ (example specs for other shot types), the README and docs/media/ (documentation images). - Nothing is sent anywhere during installation itself; the only download at install time is the repository from GitHub at the pinned commit. No script is run during installation, no key is asked for, no package or browser is installed, and there is no telemetry in the perimeter. - What leaves this machine at use time, disclosed here before it ever happens — using the skill is a separate step that only starts when I hand over a photo and ask for a video: (a) Reading the photo is local only: spot.py "exif" opens my photo with Pillow (and pillow-heif for HEIC) on this machine and prints its EXIF — GPS coordinates (WGS-84), shooting direction, altitude, time, camera model, and ISO/shutter/aperture/focal length. Nothing about the photo is uploaded for this. The photo is copied into a local project folder under ~/Documents/map-motion/<project>/, and those coordinates are written into the local spec file. (b) Amap (Gaode) lookups: spot.py "find" sends my search keyword and city, plus my AMAP_KEY as a query parameter, to https://restapi.amap.com/v3/place/text (POI search). At compile time, scripts/amap.py sends any place given as a NAME or address (not as raw [lng, lat] coordinates — coordinate pairs are resolved locally with no call) to https://restapi.amap.com/v3/geocode/geo, falling back to /v3/place/text, again with my key in the query string; responses are cached under ~/.cache/map-motion/api/. So: place names I ask about and my Amap key go to Amap; raw coordinates typed into the spec do not. (c) Map tiles at render time: render.py starts a server on 127.0.0.1 only and fetches map tiles through it — for style "satellite" (China) from Amap tile hosts webst0*.is.autonavi.com (satellite) and wprd0*.is.autonavi.com (road-name overlay), sending only tile x/y/z numbers plus a Referer of https://www.amap.com/; for style "satellite-world" (outside China) from Esri, https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/... Tile numbers pinpoint the camera/target area being rendered, so those hosts learn which area the video covers; tiles are cached under ~/.cache/map-motion/tiles/. (d) My photo itself is never uploaded by this code: render.py serves it only to the local headless Chromium through that 127.0.0.1 server, the Live Photo MOV (if I provide one) is cut into frames and its original audio extracted locally by ffmpeg, and the finished video is a local file. But the video itself displays the photo plus the camera position's latitude/longitude under the card — if I publish the video, I am publishing where the photo was taken; and per SKILL.md, never commit my photo into a public repository, and warn me if the photo contains recognisable people. (e) Present in the copied engine but NOT called by photo-spot's snap flow: scripts/elev.py (would send coordinates to OpenTopoData, https://api.opentopodata.org) and scripts/osm.py (would send area queries to OpenStreetMap Overpass mirrors) are only imported at compile.py startup; render.py also contains, for the 3D mode this skill never uses, a one-time download of maplibre-gl.js from unpkg.com and DEM tiles from s3.amazonaws.com. If I later use other map-motion shot types, those sends can happen — they are not part of this skill's flow. (f) First-use downloads: the wrappers spot.sh and make.sh run Python via `uv run --with ...`, so on first use uv downloads certifi, pillow, pillow-heif / pillow / playwright from PyPI, and Playwright's Chromium is downloaded once — package downloads only, no user data. - If my photo has no EXIF GPS, SKILL.md forbids silently guessing: the location is estimated from the picture, you must show me the top candidates and let me confirm before rendering, and the delivery must say plainly which coordinates came from EXIF, from an Amap POI, from public sources, or from estimation (an estimated camera spot can be kilometres off), and which EXIF values shown in the viewfinder are illustrative. Amap POI results can themselves be kilometres off for major peaks — SKILL.md says to prefer published summit coordinates there. - Do not set or ask for AMAP_KEY during this install, do not run spot.py, make.sh, compile.py, render.py or any other script, do not run uv or playwright, and do not render any video: setting up the key and the first-use downloads is my decision, later, when I actually ask for a photo-spot video. 3. When I say "yes, install", install it as skills, keeping the repository layout: copy the 21 engine files into a folder named "map-motion" in the agent's skills directory (SKILL.md and LICENSE at its root, scripts/, assets/ and references/ under it, including the photo-spot/ folder's 7 files inside it at map-motion/photo-spot/), and make "photo-spot" available as its own skill in a folder named "photo-spot" next to it — the upstream route is a symlink ~/.claude/skills/photo-spot pointing at the photo-spot folder inside map-motion; a plain copy of those same 7 files is equally fine, as long as every installed file matches its fingerprint. Any other route is fine only as long as every installed file matches its fingerprint. 4. Verify with no network calls: both frontmatters valid (name: map-motion in the engine SKILL.md, name: photo-spot in photo-spot/SKILL.md), all 28 files in place with matching fingerprints (the photo-spot files counted once, whether reached through the map-motion folder or the photo-spot folder/symlink). Do not run any script to verify. 5. Report what was installed, where, and what I still need to do myself (for example: get my own free Amap Web Service key and set AMAP_KEY or ~/.config/map-motion/amap_key myself; make sure uv and ffmpeg are installed; accept that the first actual use downloads the Python packages and Playwright Chromium described in point 2; hand over the original photo file — exported unmodified, so its EXIF GPS survives — rather than a chat paste or screenshot; confirm the camera and subject locations with you before any render if the photo has no GPS; using the skill is a separate step that only starts when I ask for it, and the use-time sends disclosed above happen only then). GitHub is optional: if I have a GitHub account or the gh CLI, you may use it; otherwise public access is fine. Never require it unless it's in the prerequisites above. Rules: don't touch anything outside the temp folder and the install targets. If anything looks off, stop and ask me.
Saved to your recent installs. Find it anytime on /connect.
Questions
How do I install a build?
Every product page includes a copy-paste install prompt. Paste it into your Muse and it sets the build up for you — no manual configuration.
Where does my money go?
Straight to the seller. Skill Harbor never processes payments: checkout happens on the seller’s own page, usually Stripe.
What does the ✓ next to a creator’s name mean?
It means we confirmed the identity of the person behind the listing. It says nothing about the code itself — always check a build before installing it.