一个知识点 → 一期暗金文献风纯音乐知识短片
参考样片:ep23-wheat-chessboard(棋盘上的麦粒,33.5 秒)。用户认可的就是这一期:第一秒一个发光的视觉锚点;锚词「一点点」在配乐 17.45 秒的重拍上砸出来;字幕卡小节线、中英双语;结尾把锚词重新定义,再抛一个问题。
方法论来自一篇「Vibe 知识视频」起号复盘(同一套提示词做三条,数据差十几倍)。决定成败的是四件事:开头留住人、音乐 / 画面 / 文案的高潮落在同一帧、抛一个人人有答案的问题、转场像一个连续长镜头。 下面每一步都在为这四件事服务。
一口气做完第 0~7 步,中途不等用户确认,每步做完用一两句话同步进度。不导出、不提交 git,除非用户另外要求。动手前先读工程根目录 CLAUDE.md、src/library/README.md 里「暗金文献风 gilded/」一节。所有 npm / npx / node 命令前先 export NODE_OPTIONS=--max-old-space-size=4096。
规格
| 项 | 默认 |
|---|---|
| 画面 | 横屏 16:9(1920×1080,30fps),暗金文献风(src/library/gilded/),独立组件,不走 Show |
| 时长 | 30~60 秒,跟着配乐的段落走;用户给了时长按用户的 |
| 口播 | 无。字幕就是旁白:每屏一句中文 + 一行英文斜体 |
| 配乐 | 音乐库 public/music/(audio/music.mjs 的 cutMusic),从第 0 秒放,响度 −16 LUFS |
| 音效 | 一层很轻的底噪 + 5~8 处:重拍冲击、关键转场、关键结论、片尾 |
0. 定期数和目录
- 期号取
src/episodes/里最大的下一个,作品 IDepNN-英文短名,下面记作<期>。 - 代码
src/episodes/<期>/(timeline.ts+Ep*.tsx),音频public/audio/<期>/(不进 git),配乐脚本audio/episodes/<期>.mjs,测试tests/episodes/<期>.test.ts。
1. 选配乐,实测卡点
先定音乐,因为整片的时间结构是从音乐里长出来的。
- 默认用音乐库里的曲子(目录见
public/music/README.md);用户指定了新曲子,先放进public/music/,在audio/music.mjs的TRACKS和 README 各补一行。 - 跑卡点脚本,拿到起音、小节长、第一个「换气 + 重拍」:
BPM 明显是半速或 1.5 倍时,用uv run --with numpy python .claude/skills/weilanx-creator-gilded-video/scripts/beats.py public/music/<曲子>.mp3 --to 40--bpm LO HI收窄范围重跑。脚本会用「起音到重拍是整数个小节」反推精确小节长,用精修后的小节长,不要用自相关的粗 BPM(2% 误差 8 个小节就漂 0.3 秒)。 - 把结果写进
TRACKS的note。we-never 的数据:起音 0.36 秒、一小节 2.136 秒、第一个重拍 17.45 秒(第 8 小节)。 - 详见
references/配乐与卡点.md。
2. 找锚词,写字幕
详见 references/叙事与字幕.md。核心:
- 先找锚词,再写任何字幕。 2~4 个字,是这个知识落在普通人生活里的处境,不是术语本身(指数增长 →「一点点」,沉没成本 →「舍不得」,幸存者偏差 →「看不见的人」)。好锚词让观众觉得「说的就是我」,一个词能装下整个原理,结尾还能被重新定义。
- 钩子段(起音 → 重拍前):第一句用第二人称写观众正在经历的悖论;中间几句让现象一点点展开;重拍前那句只说一半,以「——」结尾,留给锚词补完。
- 重拍:锚词本身就是那一刻的字幕,不再另配字幕;0.6 秒后在下方浮出「术语中文 · English」。
- 高潮之后才讲原理、人物、数字;可以再用一次小一号的爆点(全片最多两次),同样用「话说一半 → 大字补完」。
- 结尾:一句重新定义锚词,最后一句抛一个和观众有关、每个人都有自己答案的问题(以「?」结尾)。
- 每句中文不超过 18 字,英文是意译不是逐字翻译;每句都从小节线开始,停 1~2 个小节。
- 片中每个年份、人名、数字、引文都要核对;估算的数字在画面上用小字写清口径(ep23:「估算:每粒小麦约 0.05 克……」)。
3. 写 timeline.ts(全片的唯一时间表)
照 src/episodes/ep23-wheat-chessboard/timeline.ts 的结构写:
BAR、BAR0、barSec(k)、fr(sec):小节网格。HIT(第一个重拍帧)、HIT2(可选的第二个爆点,取小节线)、DARK_FROM(重拍前约 0.7 秒起收暗)、FREEZE = 3(重拍前 3 帧静止)。ANCHOR、TERM、CUES: [小节号, 中文, 英文][]、SHOTS(镜头段落,首尾相接)、SFX: [文件, 帧, 音量][]。- 片中的数字用函数算出来(BigInt 处理大数),测试里核对。
4. 做画面
详见 references/画面与转场.md。要点:
- 第一秒就要有视觉锚点:一个发光的小东西(一粒麦子、一枚硬币、一个红点),眼睛一进来就落在它身上。不要从空画面或一根慢慢画的线开始。
- 转场优先用同一个元素贯穿前后两个画面:镜头从一粒麦子拉远成整张棋盘、棋盘缩到一边让出位置画曲线、大字缩回成一粒麦子。淡入淡出只作辅助。
- 重拍那一帧:之前画面整体收暗到约 94% 黑、最后 3 帧静止;重拍帧光晕骤亮 + 锚词(约占画宽 1/3)从 1.12 倍收到 1 倍 + 一圈光环从字背后扩出去(
Smash,ep23 里有现成实现)。 - 节奏舒缓:镜头缓慢推拉、元素柔入柔出,不弹跳、不旋转、不快切。
- 素材库组件:
GildedBgDustGrainGCaption(en参数出英文行,【词】变金色)、goldText、RedStamp、GoldTreeBellBarsGaltonBoardRatioChartDotFieldGoldWheel等;一期专用的组件写在本期目录,下次还能用的挪进src/library/gilded/并补 README。
5. 配乐和音效
audio/episodes/<期>.mjs:cutMusic({track, start: 0, duration, ep, fadeIn: 0.02, fadeOut: 2}),再生成本期专用的冲击音效和底噪(照抄 ep23 的脚本,冲击音效峰值压到约 −6 dBFS,否则叠在配乐上会爆)。运行node audio/episodes/<期>.mjs。- 共享音效在
public/audio/sfx/(paper、whoosh、magic、ding 等),音量 0.15~0.25,不抢音乐。 - 听不到声音要如实说:只报响度和峰值数字,听感请用户确认。
6. 注册、测试、抽帧自查
src/Root.tsx注册<Composition id="<期>" …>。- 测试照
tests/episodes/ep23-wheat-chessboard.test.ts:高潮离实测重拍不超过 2 帧;字幕按小节递增、在片长内、中文 ≤ 18 字、都有英文;锚词在开头和结尾出现;重拍前一句以「——」结尾;最后一句以「?」结尾;镜头段落首尾相接;数字核对。 npm run typecheck && npm test。- 抽帧:单独看重拍前后 6 帧(重拍 −1.15、−0.65、−0.45、−0.35、+0.05、+0.55 秒),确认「收暗 → 静止 → 爆发」;再每个镜头段落抽一帧,查文字重叠、出画、看不清。一次只渲染一帧(并行渲染会内存溢出):
npx remotion still src/index.ts <期> /tmp/<期>/f.jpg --frame=N --scale=0.5 --timeout=120000
7. 预览,等确认再导出
- 打开 Studio(已经开着就直接给链接):
http://localhost:3000/<期>。 - 回复里给:锚词和它出现的所有位置、分镜表(时间 | 画面 | 转场 | 中文字幕 | 英文字幕 | 音效)、配乐卡点数据、片中所有需要核对的数字和说法、配乐授权情况。
- 用户确认后:
npm run export -- <期>→out/<期>/<期>.mp4,报告分辨率、时长、整片响度和峰值。 - 收尾:
styles/我的风格/暗金文献风/README.md的期数表补一行;配乐用了哪段记进public/music/README.md。
发布提醒
- 配乐授权没确认的(比如 we-never),只能本地 demo;公开发布前换成有授权的曲子,换曲后重跑第 1 步,改
timeline.ts的网格和HIT,画面会跟着对齐。 - 发抖音时带 #Vibe知识大赏 等活动话题。