Map Motion
Turn a JSON shot list into a map-animation video (vertical/horizontal MP4 + GIF): AMap (Gaode) resolves place names and supplies real driving/walking/cycling routes and district boundaries
- What
- Turn a JSON shot list into a map-animation video (vertical/horizontal MP4 + GIF): AMap (Gaode) resolves place names and supplies real driving/walking/cycling routes and district boundaries
- 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 a JSON shot list into a map-animation video (vertical/horizontal MP4 + GIF): AMap (Gaode) resolves place names and supplies real driving/walking/cycling routes and district boundaries, OpenStreetMap supplies park/site outlines, SRTM elevation comes from OpenTopoData/AWS, and headless Chromium + ffmpeg render frame by frame. Fourteen shot types (globe dive, "I am here" locate with coordinate card, pins, routes with elevation profile, flight arcs, district highlights, radiating flights, multi-stop trips with photos, photo wall, snap camera-spot reveal, guess-the-place, and more), a 3D terrain mode and a sun mode, in fourteen styles from AMap/satellite tiles to vector journal, neon and blueprint. 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 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
- 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: none for the install itself: no account, no API key, no paid service, and nothing else to insta · Prérequis : aucun pour l'installation elle-même : aucun compte, aucune clé API, aucun service payant, et rien
- uses API keys or tokens — Prerequisites: none for the install itself: no account, no API key, no paid service, and nothing else to insta · Prérequis : aucun pour l'installation elle-même : aucun compte, aucune clé API, aucun service payant, et rien
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: none for the install itself: no account, no API key, no paid service, and nothing else to install first. For using the skill afterwards, read this first — use requires things this install does NOT set up: (1) my own free AMap (Gaode) Web Service API key, without which compilation fails outright (see the sends in point 2: the key is sent only to restapi.amap.com, as that service's own key); I provide it later myself, as the environment variable AMAP_KEY or in ~/.config/map-motion/amap_key — never in a spec or project folder; AMap registration is free with a daily quota, it is not a paid plan. (2) uv and ffmpeg on my machine. (3) On first use only, downloads that happen then, not now: uv fetches the Python packages named in scripts/make.sh (certifi and Pillow for compiling, Playwright and certifi for rendering), and Playwright downloads its Chromium browser (uv run --with playwright playwright install chromium) — SKILL.md lists that as a first-use step. The skill turns a JSON "shot list" spec — place names, routes, dates and local photo paths that I write or confirm — into map-animation MP4/GIF videos; what leaves this machine at use time (place names and coordinates to AMap, OpenStreetMap/Overpass, OpenTopoData and tile servers) is disclosed in full in point 2, before it ever happens. Install "map-motion" for me. It builds map-animation videos for travel and explainer videos from a JSON shot list: compile (AMap resolves place names, fetches real driving/walking/cycling routes and district boundaries, OpenStreetMap supplies park/site outlines, OpenTopoData/AWS give elevation) then frame-by-frame rendering (headless Chromium canvas + ffmpeg) to vertical/horizontal MP4 and GIF. Fourteen shot types: globe dive to a place, Vlog "I am here" locate with coordinate card, pins, route tracing (driving/walking/cycling/GPX, vehicle follows the line, odometer, elevation profile), flight arcs, district highlighting, one-to-many radiating flights, multi-stop trips (routes + stamps + photos + return leg; an avatar field switches a trip to a cartoon-character vlog mode using avatar images I supply), photo wall ending, overview, title cards, camera-spot reveal ("snap"), guess-the-place, plus a 3D terrain mode (mode "3d": real terrain, satellite texture, follow-the-track playback) and a sun mode — all implemented in this root skill's own scripts (scripts/terrain3d.py, scripts/sunlight.py), not in the sibling folders. Fourteen styles (AMap standard/dark/gray/sepia/journal tiles, AMap satellite, Esri world satellite, and vector dark/light/journal/vintage/neon/ink/blueprint). Repository: https://github.com/SpaceZephyr/map-motion (the skill is the repository ROOT at the pinned commit: SKILL.md plus scripts/, references/, assets/ and the root files — 47 files listed in point 1. The sibling skills map-3d/, photo-spot/ and travel-vlog/ and the docs/ illustration folder are NOT part of this install — see point 2.) 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 the 47-file perimeter listed below from that checkout (everything except map-3d/, photo-spot/, travel-vlog/ and docs/). Then compare every copied file with the fingerprints recorded for this listing on 2026-10-19: [FINGERPRINTS] - .gitignore: SHA-256 7b5e3485bca1a2f1aee193d16f8b2fb5860755c9239e3485edc05861b2563947 - LICENSE: SHA-256 503807b77b7096091e3be3fdec62cfdc41f7de2a1b805a05e586edae7a7a657c - README.md: SHA-256 d7fc885cb030037b7a3e8aa8e901cd8468c619f69564c589a8e1b00adf417634 - SKILL.md: SHA-256 d3848172be1eca9b4cd8ba3e51a76bb5ff5a8e39b8d421a357e0b5e12f159790 - assets/china.json: SHA-256 df6c10e3d0be10052355a958812a5decd60a544b858b2934b170ca0fdebf2985 - assets/examples/cycling_trip.json: SHA-256 0a8a9d9d623a5fcdb29ac935e61763a274bb2624bf7aca9c481066411f51389a - assets/examples/drive_follow.json: SHA-256 d8841616d9a21550fccd22ad41a1039d4676989bccd1d38b1a042a7019637701 - assets/examples/flight.json: SHA-256 512638e5b0c301fcb1f507361f520bdcc569361e638408d22de3869e5fb7d518 - assets/examples/globe_dive.json: SHA-256 8e11c218b033790744c8cd4f09f8afa6e1963101ac6ebb7411d3e35971f5af9e - assets/examples/hike_elevation.json: SHA-256 b3b5e74502e5b303765882b121e9805bea5091db67d8af60664c9b7dd825352e - assets/examples/park_locate.json: SHA-256 497066f5bc7bde2541fd1002604372e8cae511ec0e269121e4c9ea6e90524233 - assets/examples/park_walk.json: SHA-256 4d16c5e317b6a42b7dbf5ffe4f58edc33f22173563cf47795403893ef52cf3f8 - assets/examples/radiate.json: SHA-256 1fa2b5bc128f598ebfadf4a2216dab8be35a37902a12c41990144a3deab81eb1 - assets/examples/region.json: SHA-256 53246ac098f88d1ee1da70cb037f801a2b55033160cb3ea548ae15836deb98b5 - assets/examples/road_trip.json: SHA-256 669fa694b0e24f1a56fb888c4a4c84813c5087b0af3b9509f74be3b1849dd49e - assets/examples/showcase.json: SHA-256 0ffc405e08220fe0e68e5a8b4fd5e22e5fc91feb1490a78cffb8703eae9fd242 - assets/examples/vlog_locate.json: SHA-256 1b9f3689354c5471e06a5b15db2563a80bf53f21e162c0177e5a2d754e283a4c - assets/examples/vlog_locate_night.json: SHA-256 6095ce35948007efb048f851affed3f6a012577751c0dae740e7fc26a2232444 - assets/fonts/Anton-400.woff: SHA-256 791375bdbed00de4a3aad4811291220ead0e1405d6f8b5bdbf109798c8359ac5 - assets/fonts/LICENSES.md: SHA-256 d0eae41ae5d5a1f8a55ee0e153f4f197f6090df826f871c232b4dc6fbd31e5b1 - assets/fonts/LXGWWenKai-500.woff: SHA-256 734bd187392579417ac83effe31d37b9de43c7b290bcb400800456511ed79e8f - assets/fonts/NotoSansSC-700.woff: SHA-256 dd0d39a9780eb995c499af0c20cca93b1dfdda865da70871a20890b3e406b968 - assets/fonts/NotoSansSC-900.woff: SHA-256 d2d8a42438b18b65b6577434df4e41bb08c6b5051281757849af00ab743bb58f - assets/fonts/OFL.txt: SHA-256 67c5d5206b96f8340b95fabd02ae60701e0b20ce2594d976216f1065e5aa3822 - assets/land.json: SHA-256 e8546a66c5ad7545d60097580fd8abd154c6257ae4b5022ff2dfadc62fc4ce46 - references/amap.md: SHA-256 2c2e6b441b2fdd5361a10c9a58c44f5b6ecc39a880ba43a1d2a8bca841d0a85d - references/spec.md: SHA-256 14d38fb1e8185922b2f3ac5f581ac966b5255f9cc3fced69ed22fbcd91e3ab57 - scripts/amap.py: SHA-256 7db7efbaf5b63362ca8078d88da9f0606e5c38a92410c3643e0f19072486b92d - scripts/audio.py: SHA-256 4785e478cea1ff36158f3db471214706465fa7cd8946e516c5f4faad6d52770e - scripts/compile.py: SHA-256 32420d87aa526d5bf86ea526dfb61e63d4ba2b31666c5828bbb4d5bbd3a5879e - scripts/dem.py: SHA-256 c193482183aa1e0bb54e8b7661d77e6dde0a6e56339c2e3c229439013d588a9c - scripts/elev.py: SHA-256 ec41a716692742c58a80596b1df804db02d8f7017108ad2d0797b2b1b5b588a7 - scripts/geo.py: SHA-256 9a7b1f555e7a54c0b5f15504a9aa213d4dc99b3f11c410404d6ab57cf30e7b63 - scripts/make.sh: SHA-256 9fc63a0c7933448d46b28b7352d233d88d251399205d6d52015f868cb21c49af - scripts/osm.py: SHA-256 3e30d7b0d8288f5a62de626f428899cddf9c7ca5b3e94623ebf7892a307421e2 - scripts/qa.py: SHA-256 9b87b89c690d22aeecf0441685f2d7489a2379cf9a8c9514045e2438eeb19baa - scripts/render.py: SHA-256 fd5eb323b0207c9b9920aa6dc24982113a04020b582fe67266f8359a57db5ecd - scripts/runtime/hud.js: SHA-256 143017794af92ca455a6caa8ec3c1811171ee80b99c0d875442ce10a9983f4db - scripts/runtime/index.html: SHA-256 898c81ea79e2828b5fb6d37c80c0ca1fe9048640ab78523d4670a0749cedd34d - scripts/runtime/mm.js: SHA-256 f943260dea924193a67eb6df587b04053a16f844ed0d930fab35def86bbf31f3 - scripts/runtime/qa.js: SHA-256 8c761421f289a378b8341fac965a1f516567899eda9cb5786ac1fc8f792e801a - scripts/runtime/t3d.js: SHA-256 a891d9343f8471407c1b39bd6d5fe2d2a796d0a81e479aa6c61663e97fb7a306 - scripts/runtime/terrain.html: SHA-256 61cc9712c9323e2ba22ea1d5bb7d9e19bf5bfe52b518a1edb717528c80e7954c - scripts/status.py: SHA-256 eca7060ddc17aef9262d5b0c7536449de7f6856afe4184411be43351f3c5f0d5 - scripts/sun.py: SHA-256 2c6ce15ccc443a6fa0935d31ca76fdca1cea4d2d82c6119598757f91269db2bc - scripts/sunlight.py: SHA-256 577c7613504d84a14c5813a7ace7534c81dc0dee8bb0c295fcb7a7f58819dadc - scripts/terrain3d.py: SHA-256 cd2741899a619a477c917e6107a04033157a3e92bf29b1662c94ff65c6602cc2 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 SKILL.md in full, both files in references/ (spec.md, amap.md) and every file in scripts/ (amap.py, audio.py, compile.py, dem.py, elev.py, geo.py, make.sh, osm.py, qa.py, render.py, status.py, sun.py, sunlight.py, terrain3d.py and scripts/runtime/hud.js, index.html, mm.js, qa.js, t3d.js, terrain.html), 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: - Perimeter and cross-dependencies, exactly: the root skill is self-contained in the 47 files above. Its code never imports or calls anything in map-3d/, photo-spot/ or travel-vlog/: the 3D terrain compiler is scripts/terrain3d.py, the sun compiler is scripts/sunlight.py, and the snap (camera-spot) and trip avatar/vlog shots are shot functions inside scripts/compile.py. The dependency runs the other way — the three sibling skills reuse THIS engine (map-3d/scripts/m3d.py, photo-spot/scripts/spot.py and travel-vlog/scripts/vlog.py all point back at the root scripts/) — so they will not be installed by this install, and one documented detail lives outside this perimeter: references/spec.md points to map-3d/SKILL.md for the full "sun" mode spec fields. Root runtime files load only root assets: scripts/runtime/mm.js and hud.js load assets/land.json, assets/china.json and the four fonts in assets/fonts/ (Anton-400, LXGWWenKai-500, NotoSansSC-700, NotoSansSC-900) through the local render server, and SKILL.md's workflow copies a starting spec from assets/examples/. docs/media/ (18 images, about 37 MB) is illustration for the README only and is never read by any code. - 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 Chromium or package 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 ask for a video, and compile/render are run then via scripts/make.sh (uv run --with certifi --with pillow for scripts/compile.py, uv run --with playwright --with certifi for scripts/render.py, so uv may download those packages from PyPI on first use, and Playwright's Chromium must already have been fetched by the first-use step in the prerequisites): (a) AMap Web Service, https://restapi.amap.com — scripts/amap.py sends my AMAP_KEY (as the "key" query parameter, to AMap only) together with what my spec names: place names/addresses to /v3/geocode/geo (with a fallback keyword search to /v3/place/text), origin, destination and waypoint coordinates to /v3/direction/driving, /v3/direction/walking or /v4/direction/bicycling, and district names to /v3/config/district. In other words, the places, addresses and route endpoints in my shot list go to AMap (AutoNavi). Responses are cached under ~/.cache/map-motion/api/. (b) Map tiles, fetched by scripts/render.py through its local proxy and cached under ~/.cache/map-motion/tiles/: AMap tiles from wprd0{s}.is.autonavi.com and webst0{s}.is.autonavi.com (tile x/y/z and style only, with a Mozilla/5.0 user agent and Referer https://www.amap.com/, no key), Esri World Imagery from server.arcgisonline.com for the satellite-world style and all 3D satellite imagery (tile z/y/x only), and AWS Terrain Tiles from s3.amazonaws.com/elevation-tiles-prod/terrarium/ for 3D terrain and elevation (scripts/dem.py fetches the same tiles directly; tile coordinates only). (c) OpenStreetMap Overpass — scripts/osm.py POSTs a query to one of https://overpass-api.de/api/interpreter, https://maps.mail.ru/osm/tools/overpass/api/interpreter or https://overpass.kumi.systems/api/interpreter (tried in rotation, cached under ~/.cache/map-motion/osm/): for an "area" shot the query carries the place name from my spec and a bounding box around its AMap-resolved coordinates; for a 3D track built from waypoints it carries the bounding box of those waypoints. (d) OpenTopoData elevation — scripts/elev.py sends coordinates (converted back from AMap GCJ-02 to WGS-84, in batches of 100 as lat,lng pairs in the URL) to https://api.opentopodata.org/v1/srtm30m when a shot asks for altitude or an elevation profile; results cached under ~/.cache/map-motion/elev/. (e) 3D only: scripts/render.py downloads MapLibre GL JS 5.24.0 from https://unpkg.com/[email protected]/dist/maplibre-gl.js on first 3D render and caches it under ~/.cache/map-motion/vendor — a library download only, no user data is sent to unpkg beyond the request itself. - What stays local at use time: my photos are never uploaded by this root skill — scripts/render.py serves only the specific local photo/avatar/Live-Photo files named in the timeline, via its 127.0.0.1 server, to the local headless Chromium page that draws the frames, and ffmpeg assembles the MP4/GIF locally; audio.py synthesises the music and sound effects locally. This root skill does not read photo EXIF itself (that reader lives in the sibling photo-spot skill, which is not installed here): if I put GPS/EXIF or GPX coordinates into a spec marked "wgs84": true, compile converts them locally, and only the resulting place/route/coordinate queries listed above leave the machine. AMap tile use is unofficial: personal/learning videos are fine with the on-screen AMap attribution kept, commercial use needs AMap authorisation or a vector style — the same applies to Esri imagery. - Outside this perimeter, disclosed so there is no surprise later: the sibling travel-vlog skill (not installed here) can generate a cartoon avatar from my photo via the third-party LabNana image API, which would send that photo to LabNana under my own LabNana key — that is the sibling's behaviour, described in this repository's README; nothing in this root skill calls LabNana, and installing this listing does not enable it. - Do not run make.sh, compile.py, render.py or any other script during this install, do not install Chromium or any package, do not set or ask for AMAP_KEY, and do not make any video: setting up the AMap key and the first-use downloads is my decision, later, when I actually ask for a video. 3. When I say "yes, install", install it as a skill: copy the 47-file perimeter into the agent's skills directory, in a folder named "map-motion", keeping its structure (SKILL.md at its root, scripts/, references/ and assets/ as in the checkout, and no map-3d/, photo-spot/, travel-vlog/ or docs/ folder inside it). A manual clone followed by copying that perimeter into ~/.claude/skills/ is the route described here; any other route is fine only as long as every installed file matches its fingerprint. 4. Verify with no network calls: frontmatter valid (name: map-motion), all 47 files in place with matching fingerprints, and no sibling or docs folder installed. Do not run any script in scripts/ to verify. 5. Report what was installed, where, and what I still need to do myself (for example: get a free AMap Web Service key and provide it as AMAP_KEY or ~/.config/map-motion/amap_key before first use, knowing the places, addresses and coordinates in my specs go to AMap and the other use-time sends disclosed above happen only when a video is compiled/rendered; make sure uv and ffmpeg are installed; on first use, let uv fetch certifi/Pillow/Playwright and install Playwright's Chromium; provide the shot list content myself — places, routes, dates and local photo paths; using the skill is a separate step that only starts when I ask for a video). 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 target. 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.