---
name: wallstreet-explainer
description: 华尔街式的财经/科技解读短片（1–3 分钟、16:9、没有主持人出镜）：用真实的人、真实的新闻和官方画面作证据；当事人的实拍抠像替代主持人（人站在巨字前面、人身后换背景、横推换人）；图形舞台（厚玻璃圆盘、大数字、白底图表）放在一个有前后层的 2.5D 世界里，用镜头把钱和关系演出来，每一镜都接住上一镜往下推。教的是设计思路、动效原理（为什么不像 PPT、不像 AI）和风格语言，外加一套工具（找片下片看片抽帧、新闻原文截图、GPU 逐帧抠人、临时配音和时间线、逐帧渲染、2.5D 相机小工具、镜头运动自检、混音），不给可以照抄的画面模板。用户说"wallstreet-explainer""做一条财经/科技解读""把一笔账讲清楚""巨头砸钱/估值/营收/资金循环这类题目"时使用；有真人口播出镜的片子不用这个。
---

# 华尔街式解读片（wallstreet-explainer）

**讲一笔大账：真的人、真的新闻、真的画面作证据，图形舞台把数字和关系演出来；每一镜都接住上一镜的东西往下走，观众始终知道“现在在看什么、为什么看这个”。**
**动的是镜头和世界，不是元素自己演：镜头在有前后层的舞台里推、拉、摇，去找正在说的那个东西；东西在原地换状态。每一下动作都对着那句话的意思。**

## 这份 skill 是什么

- **是**：一套设计思路（每一镜放什么、为什么、凭什么接下一镜）、一套动效原理（从三条同类参考片逐帧量出来：为什么它不像 PPT、不像 AI，手法清单和量化目标）、一套风格语言（舞台、巨字、抠像、圆盘、数字、图表、原文高亮的具体做法，外加一份开头钩子菜单），以及一套工具。
- **不是模板**。没有能复制的画面工程，也没有固定的镜头顺序。每条片的画面都要从它自己的文案和素材里现想。`examples/ai-burn-money/` 记录的是一条片子怎么想出来、在哪里摔过跤，不要照搬它的镜头。

- **慢推、数字滚动、实拍上压字，参考片都在用**。廉价的不是这些手法，是做法。判断用三句话：删掉它观众少懂了什么？是镜头在动、东西在换状态，还是元素自己在演入场？这一层是真的、具体的吗？

动手前先读 `references/thinking.md` 和 `references/motion.md`，再按需要读其他几份。

## 流程：每一站停下来给用户看

审美由用户把关。不要一口气出成片；每站给出具体的东西，等他点头再往下走。

| 站 | 做什么 | 给用户看什么 |
|---|---|---|
| 0 选题 | 题目要同时满足“现在热”和“看完能带走点什么” | 两三个题目，每个附一句钩子 |
| 1 文案 | 口语、第一人称，句句往下接；插原声的地方先写铺垫句（`references/audio.md`） | 全文。点头之前不做正式配音 |
| 2 导演表 | 见下面“导演表”一节 | 要点：开头怎么抓人、每处怎么接、要不要加铺垫句 |
| 3 素材 | 官方高清片 → 新闻原文 → 当事人原声 → 当事人抠像用的整段实拍（没有切点、有对得上台词的动作）。先拼联系表看过，再定入点，逐帧查切点（`references/sourcing.md`） | 关键素材（可选） |
| 4 配音和时间线 | `scripts/temp_voice.py`：先用临时语音排出时间线，画面全部挂在字上 | — |
| 5 开头 | 先挑 3 个机制不同的钩子，各做 5–8 秒粗剪给用户选（`references/opening.md`）；选中的再做成从 0 秒到第一个换段处的小样（15–20 秒，带声音） | 3 个钩子粗剪 → 选中后的开头小样 |
| 6 全片 720p | 按导演表铺完；每写两三镜截静帧看，关键动作看连续帧（`strip.py`）；交片前跑 `motion_check.py` | 720p 全片、抽帧图，再点出两三处请他重点看 |
| 7 成片 | 改到满意；换正式配音；出 1080p，只渲一次 | 1080p |

每次交付都要做到：
- 用 `ffprobe` 验证文件能打开。
- 自己逐镜看过静帧和联系表，关键动作看过连续帧。
- 放进一个固定的审阅文件夹，用编号加中文名命名，旧版本加 `旧_` 前缀。
- 说清楚这版改了什么、哪些量过、哪些要用户自己听或看。

## 导演表

全片只有这一份计划。用户拿它核对画面，做的时候照它做，审片时拿它对照。每一镜写这几列：

| 镜 | 时间 | 文案 | 屏上是什么，在干什么 → 停下来时留下什么 | 观众多懂了什么 | 承担 | 读懂时刻 + 停留 | 承接 |
|---|---|---|---|---|---|---|---|

- **观众多懂了什么**：一句具体的话，和上一镜的不一样。写不出来，这一镜就该删或者重想。
- **承担**：这一镜靠什么让人看懂。人物 / 实证（真素材、原文）/ 构造（圆盘、图表）/ 文字（大字、结论）/ 混合。
- **承接**：上一镜留下的哪样东西被这一镜接住，接法写成 `续 / 切 / 带过 / 推近 / 展开 / 换章` 加上那样东西。第一镜写 `—`。
- 在“屏上”一列里顺手写清**镜头怎么走**：每次移动的落点是谁（推到谁、摇去找谁、什么时候拉回看全），以及哪几镜用当事人抠像。
- 文案一字不改；一镜可以覆盖好几句话；时刻挂在词上（“说到‘七千’的那一刻”）。

写完做一次“读表”检查：遮住文案和“多懂了什么”两列，只读“屏上”一列，看还讲不讲得通。再查有没有连续好几处硬切、有没有停不够的镜头。示例见 `examples/ai-burn-money/director.md`。

## 读哪份

| 在做什么 | 读 |
|---|---|
| 想一镜该放什么、为什么、凭什么接下一镜 | `references/thinking.md` |
| 动起来：为什么不像 PPT/AI、手法清单、量化目标、相机和抠像的代码手感 | `references/motion.md` |
| 画面长什么样：舞台、巨字、抠像、圆盘、数字、图表、片名、字幕、实拍画框 | `references/style.md` |
| 两镜之间怎么接、运镜和动作的手感 | `references/grammar.md` |
| 开头 | `references/opening.md` |
| 找片、下片、挑入点、抠人、新闻原文、原声 | `references/sourcing.md` |
| 文案、配音、原声剪口、音效、混音 | `references/audio.md` |
| 交付前自检 | `references/review.md` |
| 实践中踩过的坑 | `references/lessons.md` |

## 工具（scripts/）

| 脚本 | 干什么 |
|---|---|
| `footage.py` | `search` 搜片 / `get` 下载（可只下一段、只下音频）/ `sheet` 带时间码的联系表 / `scenes` 镜头切点 / `extract` 抽 30fps 帧序列 / `wave` 看原声剪口的响度 |
| `snap_news.mjs` | 新闻和报告原文截图：拦广告、去浮层、等字体加载完再量关键词的框 |
| `matte.py` | 实拍逐帧抠人（GPU 上 ISNet 约 0.25 秒/帧），提示藏着的切点，只存人物外框那一块 |
| `matte_clean.py` | 抠像后处理：去细线零碎、整列抹掉贴着的椅背、写出每帧头肩中心（放人时跟住他） |
| `stage25d.js` | 页面里用的小工具：分层相机、方向运动模糊、景深、抠像跟人、巨字、眉题、实拍退成底、按十亿取整。只是工具函数，不是镜头 |
| `temp_voice.py` | `script.json` → 临时配音（edge-tts）和 `timeline.json`（每个字的时刻、原声插段、片名位置）；有正式配音时自动换上，`--asr` 重新对齐 |
| `render.mjs` | 逐帧渲染：`--stills` 看帧、`--video --range` 渲一段、`--h 1080` 出成片 |
| `strip.py` | 连续帧拼图：一个动作 8 张，查静帧看不出来的穿帮；也用来拆参考片的动作 |
| `motion_check.py` | 镜头运动自检：画面完全不动的时间、定住次数、镜头在动的时间、前后层、推拉比，和参考片的区间比 |
| `mix.py` | 配音、原声、音效、配乐（配乐给人声让路）→ -14 LUFS；`--check` 量各段响度 |

依赖：ffmpeg、yt-dlp、Python（edge-tts、numpy、opencv-python、Pillow；可选 faster-whisper；抠人要 onnxruntime-gpu 和 rembg 下载的模型）、Node 和 Playwright。安装方法见 README。

## 配音：先用临时语音

- 先用 `temp_voice.py` 出 edge-tts 临时配音，排出时间线，画面照它做。
- 文案和画面都定了，再换正式配音（任何 TTS、克隆音色或真人录音都可以）：每句存成 `voice/<id>.final.wav`，跑 `temp_voice.py script.json --asr`。
- 配音一律：切掉首尾静音、保持原速、句间停顿只由 `gap` 决定。不要事后用 atempo 加速，切掉静音以后再加速会很急促。

## 片子怎么搭（骨架，不是拿来抄的）

- 一个片子目录：`index.html`、`film.css`、`film.js`、`timeline.json`、`assets/`（实拍帧在 `assets/clips/<名>/`，抠像在 `assets/cut/<名>/`）。要用相机小工具就把 `scripts/stage25d.js` 拷进来，先于 film.js 载入。
- `film.js` 暴露 `window.ready` 和 `window.seek(t)`。`seek` 找到 t 所在的镜头（`shot(t0, t1, fn)`），调用 `fn(t)` 返回这一帧的 HTML，并等图片解码和字体加载完。同一个 t 永远画出同一帧，不依赖 CSS 动画和播放时钟。
- 时刻一律写成 `cue(句id, '词')`，从时间线里取，不写死秒数。换了配音，全片自动顺延。
- 实拍抽成帧序列，按 t 取帧，不用 `<video>`。帧数要登记，漏了会取到不存在的帧，出现黑屏或空框。
- 一镜 = 一个机位函数 + 几层画面：机位用 `camPath(t, 起点, 移动表)`，每层用 `L(机位, 上一帧机位, z, html)` 包起来，远的层 z 小，运动模糊自动算。
- 镜头之间要承接时，把上一镜的函数在它最后一刻的画面拿来做下一镜的开场（推过镜头、缩小挪走、撑开、横推出去）。这样上一镜的末态和下一镜的首态天然一致。
- 720p 看效果，1080p 只在定稿后渲一次。
