| name | promo-film |
|---|---|
| description | 用代码做产品宣传片 / 推广片 / 演示短片 —— Remotion + React 出片, 界面在片子里是重画或真机抓图的真界面,全程可版本管理、可逐帧复现; 配乐是可选的一步,要配才配,纯代码合成、无第三方素材。 当用户说「给这个产品做支宣传片 / 推广片 / 演示视频 / promo / product video」、 「发 X(推特)/ 小红书 / 官网首屏的那种短片」、「更新短片 / release 视频」、 「片子节奏不对 / 字在抖 / 想换个运镜 / 想重新配乐」、 「把这几个功能拍出来」时使用。也用于给已有的 video/ 工程改文案、改节拍、改镜头、出竖版。 不适用:需要真人出镜或实拍素材的片子;纯剪辑现成视频(那是 ffmpeg 的活); 单张封面图 / OG 图(那是静态图的活,不必为它搭一个视频工程)。 |
promo-film · 用代码拍产品片
核心:片子是一份可以编译的源码,不是一条时间线。每一帧画面都是「全局帧号」的纯函数 —— 所以节奏能改、镜头能算、字能 diff、配乐能重新生成,而且今天渲和三个月后渲逐字节一样。
技术栈固定:Remotion + React + TypeScript,1920×1080 @ 60fps 为默认画幅。
配乐是可选的一步(见流程第 6 步),要配的话纯代码合成(assets/scripts/lib/synth.mjs),
不引第三方素材。$SKILL 指本 skill 目录(Claude Code 下是 ~/.claude/skills/promo-film)。
三条贯穿全片的硬约束
先记住这三条,后面所有细节都是它们的推论。动手前把这三条念一遍,改任何一处之前再念一遍。
① 只有一套颜色、一套字体、一条缓动。
颜色逐个从产品自己的 token 文件抄过来(_tokens.css / theme.css / tailwind config),
片子里不允许出现第二套。一支片子里混三条缓动曲线,观众读到的是三只手,不是一个产品的性格。
② 那台机器是真的。 窗口里的栏宽、字号、圆角、图标字重,全部按产品真实数值搭,按逻辑像素画完再整体缩放 —— 不是把 13px 的字放大成 20px 的示意图。图标重画产品同一套字形,不引第三方图标库。
③ 不做观众察觉不到的缓慢运动。
一个 270 帧涨 2.2% 的推近,折算下来是每帧 0.005px:读不出是运镜,只看得出字在抖
(每帧按新的亚像素边界重新光栅化)。要让画面「活着」,用入场动画,不用缓慢缩放。
详见 references/camera.md,这是本 skill 唯一一个会毁掉整支片子而且在时间轴上看不出来的坑。
流程
1. 先定「讲哪几件事」,再定时长
一件事一个节拍,一个节拍 3~9 秒,全片 6~8 个节拍、30~45 秒。写成一张表交给用户确认:
| 讲什么 | 起始帧 | 时间 |
|---|---|---|
| 开场 | 0 | 0:00 |
| …… | 190 | 0:03 |
判据是减法:这个版本独有的事才进片子。已经有一支片子讲过的内容一律不重复 (老片子讲过什么,去读它的 README)。列不满六件就做 30 秒的,不要用凑数的功能撑到 45 秒。
2. 搭工程
照 references/setup.md,从 $SKILL/assets/ 拷现成的:anim.ts(缓动/关键帧/spring 词汇)、
camera.ts(镜头表)、scene.tsx(文案交接)、frames.mjs(批量审片)、
remotion.config.ts、tsconfig.json。这几份是通用的,不用重写。
要配乐才多拷一份 synth.mjs(配乐引擎)—— 不配就别拷,工程里不留用不到的文件。
3. 抄产品:设计 token 与那台机器
references/product.md。先建 design.ts(颜色/字体/阴影,全部有出处),
再搭窗口组件。这一步做扎实,后面每一场都是白捡的;这一步糊弄,后面每一场都要打补丁。
界面素材两条路:重画(默认,可动、可插值、可运镜)或 Playwright 抓真机截图
(流程复杂、有真实数据时用)。怎么选、怎么抓,在 references/product.md。
4. 一个窗口,一台摄影机
references/camera.md。全片不切镜:窗口从第二场出现到倒数第二场淡出,
中间换场靠推、拉、摇和文案交接。镜头写成镜头表(at / move / px,py / k / cx,cy),
不写成五条独立关键帧轨道 —— 原因在那份文档的开头,读完再动手。
5. 时间轴与文案层
references/story.md。窗口里发生的一切(文件树长出几行、agent 日志到第几条、
对话框开了多少、指针在哪)都是 story.ts 里一个全局帧号的纯函数;
场景组件只画文案和旁边的示意卡片,不画产品。想重排节奏,只改节拍表里那几个数字。
6. 配乐(可选 —— 先问用户要不要)
默认不配,问过再做。 出片之前明确问一句「这支片要不要配乐」,用户说要才动手。 多数推广片在社交平台上是静音自动播放的,信息本来就必须全在画面里; 而配错了乐的推广片,比没配乐伤害大。无声是一个完整的交付,不是半成品。
用户说不要:Film.tsx 里那层 <Music /> 整个不写,package.json 里的 music 脚本、
scripts/make-music.mjs、scripts/lib/synth.mjs、public/bgm.mp3 全都不要。
用户说要:走 references/music.md。make-music.mjs 写「弹什么」,synth.mjs 负责「怎么弹」,
纯代码、无素材、可商用。推广片的重点是「涨」,而涨要靠加声部,不是靠加音量。
重音落在与剪辑相同的帧上。调式选择先读那份文档的第一节 —— 有一条明确的品牌禁忌在里面。
用户想用买来的曲子:覆盖 public/bgm.mp3,长度对齐总时长即可,其余照旧。
7. 审片,再出片
references/review.md。先 SCALE=0.5 node scripts/frames.mjs <关键帧号...> 批量出图看构图,
再跑「停稳两帧逐像素相同」的抖动校验,最后才 npm run render。
出片同时出 1:1(有时还要 9:16)版本,画幅不是缩放,是重新排版。
收尾清单
出片前逐条过,任一条不过就别发:
- 停稳段落里,窗口区域逐像素帧帧相同(
references/review.md有一行命令验) - 文案没有压在窗口上:算过
cx - px·k和cx + (shellW - px)·k - 摄影机到位之后文案才进场(用
enter(f, fps, 延迟)等镜头停稳) - 每一场最后一件事做完之后留 0.7~1.3 秒收口,不留第二秒
- 全片只有一套颜色、一条缓动;片子里的数字(体积、版本、域名)跟真实产品对得上
- 要不要配乐问过用户了;配了的话重音与节拍起始帧对齐,改过节奏就重新
npm run music - README 写清楚「想改什么去改哪个文件」—— 下次改片的人(大概率还是 agent)只读这一份
什么时候不要用这个 skill
- 要真人出镜、要实拍素材 → 这是拍摄,不是渲染
- 只是把现成视频剪一剪、加个字幕 → 直接 ffmpeg
- 只要一张图(封面 / OG 图)→ 那是静态图的活,别为它搭视频工程
- 产品还没有稳定的视觉 token → 先把产品的设计系统定下来,否则片子里那台机器是假的
