---
name: photo-spot
description: "找机位 / 机位揭秘视频：给一张照片，做一段竖屏短片——卫星地球俯冲 → 落出拍照机位（相机图标）和被摄地点 → 取景扇形从机位扫向被摄地 → 取景框对焦 → 咔嚓快门声 → 照片从机位处翻折立起（3D 透视），背景是这张照片的虚化；可加 iPhone Live Photo 播放效果（真 MOV 或静态模拟）。用 map-motion 的渲染引擎。当用户说「找机位」「机位揭秘」「这张照片在哪拍的」「把照片做成地图视频」「照片定位动画」「拍照地点动画」「咔嚓翻出照片」「Live Photo 效果」，或丢来一张风景/旅行照片要做成短视频时使用。"
---

# 找机位 photo-spot

一张照片 → 13–16 秒竖屏视频：

| 时间 | 画面 |
|---|---|
| 0–6.5s | 卫星地球自转、俯冲到机位和被摄地之间 |
| 6.5–7.6s | 机位落相机图标，被摄地落针（名字＋海拔/说明）；取景扇形从机位扫向被摄地 |
| 7.6–9.2s | 取景框：三分线、参数（ISO 快门 光圈 焦距）、对焦框收缩，合焦变绿 |
| 9.2s | 咔嚓：快门帘合拢、闪白、快门声 |
| 9.4–10.6s | 照片从机位处平躺翻折立起（逐行透视，略过冲回正），背景从虚化地图过渡到这张照片自身的虚化 |
| 10.6s– | 相纸下沿手写字，卡片下方经纬度＋说明；`live` 时出 LIVE 角标并播放一段 |

渲染引擎是 map-motion（`snap` 镜头）。本 skill 管流程：定位置 → 写 spec → 抽帧检查 → 出片。

## 准备

- 需要已安装 map-motion：`~/.claude/skills/map-motion`（同一仓库根目录，见仓库 README），以及高德 key、uv、ffmpeg。
- 辅助命令：`S=~/.claude/skills/photo-spot/scripts/spot.sh`
  - `$S exif 照片` 读 GPS、朝向、时间、机型、等效焦距（→ 视角 fov）、ISO/快门/光圈
  - `$S find 关键字 --city 城市` 高德 POI 搜索
  - `$S ahead 经度,纬度 方位角 公里` 沿朝向推一个点
  - `$S sheet 静帧目录` 拼图；`$S gif 成片.mp4` 预览 GIF

## 流程

### 1. 拿照片，先读 EXIF
```sh
mkdir -p ~/Documents/map-motion/<项目名> && cp 照片 ~/Documents/map-motion/<项目名>/photo.jpg
$S exif ~/Documents/map-motion/<项目名>/photo.jpg
```
- 有 `wgs84`：这就是机位（spec 里加 `"wgs84": true`）。有 `direction`（iPhone 基本都有）就知道镜头朝哪。`exif`、`fov`、`date` 直接填进 spec。
- 没有 GPS（**聊天里粘贴的图、截图、微信传过的图都会被去掉**）：看画面猜地点，用 AskUserQuestion 让用户确认（给 3 个最像的候选，第一个放你最有把握的），不要自己拍板就开做。同时告诉用户：原图（照片 App →「导出未修改的原件」）能直接读出位置、朝向和参数。

### 2. 定机位和被摄地的坐标
- **国内**：`$S find` 搜 POI。景点、山峰、观景台用 POI 搜索，**地理编码（geocode）对景点常常报错或解析到同名商户**。挑类型是「自然地名;山」「风景名胜」的那条。
- **POI 也会错**：大山峰的 POI 可能偏好几公里（实测高德「卡瓦格博峰」偏了约 10 km）。主峰、名山用公开资料里的山顶坐标，写 `"wgs84": true`。
- **境外**：高德没数据，直接写坐标（境外 GCJ = WGS，不用转）。
- **被摄地不明确**（比如拍的是一片海）：用 `$S ahead 机位 朝向 距离` 推一个点当 target，标签写看到的东西。
- 两点距离决定画面：几百米到 30 km 都合适；太近（<300 m）扇形会很小，`frame` 调大；太远（>50 km）落地级别太低，看不清机位环境。

### 3. 写 spec
复制 `examples/` 里最像的一份改：
```json
{"size": "portrait", "style": "satellite", "tail": 0.4,
 "shots": [
  {"type": "snap",
   "camera": {"name": "钓鱼翁", "at": [114.290586, 22.292909]},
   "target": {"name": "布袋澳", "at": [114.300485, 22.272561]},
   "camera_label": "钓鱼翁 · 山顶", "target_sub": "西贡 · 渔村",
   "image": "photo.jpg", "live": true,
   "name": "钓鱼翁 · 俯瞰布袋澳", "sub": "香港西贡 · 清水湾半岛",
   "exif": "ISO 64   1/500   f/1.8   24mm",
   "fov": 40, "frame": 0.42, "dur": 6.5, "spin": -110, "focus": 1.6, "hold": 4.2}
 ]}
```

| 字段 | 说明 |
|---|---|
| `style` | **国内用 `satellite`**（高德卫星，和高德坐标对齐）；**境外用 `satellite-world`**（Esri 卫星：高德卫星境外推近就是灰底）。国内别用 `satellite-world`，GCJ 坐标叠在 WGS 影像上会偏几百米 |
| `camera` / `target` | 地点写法同 map-motion：坐标、`{"name", "at"}`、`"wgs84": true` |
| `camera_label` | 相机图标旁的字；缺省用 camera 的 name |
| `target_label` / `target_sub` | 被摄地的名字和小字（海拔、「渔村」之类） |
| `name` | 相纸下沿的手写字（照片标题） |
| `sub` | 卡片下方的说明；缺省「距被摄地 N km」。有拍摄日期就写进来 |
| `exif` | 取景框左下角参数。**EXIF 读不到时写的是示意值，交付时要说明** |
| `fov` | 取景扇形张角；EXIF 给的 fov 是真实视角（24mm≈74°），画面上嫌太宽可收到 35–50 |
| `frame` | 两点占画面的比例，缺省 0.5；标签贴边就调小（0.4） |
| `live` | `true` 静态模拟（推近＋手持晃动 2.4s）；`"IMG_1234.MOV"` 真 Live Photo（抽前 3 秒、带原声） |
| `live_at` | Live 开始播放的时刻（相对快门，缺省 1.9s） |
| `spin` | 地球起始偏多少经度（负＝从西边转过来） |
| `dur` / `focus` / `hold` | 俯冲时长 / 对焦时长 / 快门后停留（有 live 时自动加长） |

### 4. 抽静帧检查（必做）
快门时刻 ts = `dur + 1.1 + focus`（缺省 9.2s）。
```sh
M=~/.claude/skills/map-motion/scripts/make.sh
cd ~/Documents/map-motion/<项目名> && $M snap.json stills/ --stills 5.5,8.6,9.6,10.2,12,14
$S sheet stills          # 再 Read 拼图
```
逐项看：
- 8.6s：相机图标和被摄地标签都在画面里、没贴边、没互相压；扇形方向和照片对得上（从机位看过去，照片里的东西确实在那个方向）
- 9.6s：翻折中的相纸是梯形透视（不是平移）
- 10.2s 以后：相纸完整在画面内（竖图已限高），下方文字不出画；背景是照片的虚化
- 卫星底图不是灰底（灰底＝该地没有影像，境外换 `satellite-world`）

### 5. 出片
```sh
$M snap.json <名字>.mp4 && $S gif <名字>.mp4
```
快门声（和 Live 原声）自动合成进音轨；要配乐就自己混好，用 `--audio` 传入（会替换自动音效）。40 秒内的片子约 2–3.5 分钟渲染完。

### 6. 交付
说清：文件位置和时长；机位/被摄地坐标从哪来（EXIF / 高德 POI / 公开资料 / 推测）；哪些是示意（EXIF 参数、估计的机位）；用的哪家卫星图和署名。估计的机位要明说「城市级准、可能差几公里」，并提示给原图可精确。

## 踩过的坑

- 粘贴进对话的照片没有 EXIF。不要凭画面硬猜后直接出片——先问。
- 高德 geocode 对「神瀑」「卡瓦格博峰」这类景点直接报 30001 错误；用 POI 搜索（`$S find`）。
- 高德卫星在日本等境外推到 10 级以上全是灰底 → `satellite-world`。反过来国内用 Esri 会和高德坐标错位。
- 卫星样式的落针缺省是发光圆点；相机图标要 `kind: camera`（snap 已处理）。
- 经纬度 35.15° 曾显示成 `08′60.0″`（浮点进位）——已改成按 0.1″ 整数拆分。
- `--from` 截段渲染时音轨要同步跳过（已处理），否则快门声错位。
- 照片有人像时，提醒用户这是公开发布的内容；别把用户照片提交进公开仓库。
