WP

whyubel1eve/promo-film-skill

开发工具
21 stars 质量 63 趋势 18MIT

用代码做产品宣传片 / 推广片 / 演示短片。 —— 片子里那台机器是按产品真实 数值重画的(或者 Playwright 抓的真机截图),全程进版本库,逐帧可复现。

概览

用代码做产品宣传片 / 推广片 / 演示短片。 —— 片子里那台机器是按产品真实 数值重画的(或者 Playwright 抓的真机截图),全程进版本库,逐帧可复现。 一支片子在这里是一份可以编译的源码,不是一条时间线。每一帧画面都是「全局帧号」的纯函数: 文件树长出几行、agent 日志到第几条、指针在哪、主题插值到哪一帧 —— 全在 state(f) 里。 ,下游全部是相对量,动作跟着一起挪。 于是节奏能改、镜头能算、字能 diff,而且今天渲和三个月后渲逐字节一样。 :要把它装进来 → 读下面的「安装」;已经装好、要拿它干活 → 读 SKILL.md,那是操作手册,references/ 是它按需展开的细节, 本文件只是说明书。 剪辑软件里,「把第三场缩短两秒」意味着手动拖后面每一个关键帧。截图配转场的那种片子, 观众读到的是「一堆图」,不是「有人在用这个软件」。 这里反过来:改一个数字,后面所有动作跟着挪,窗口全片不切镜,一台摄影机推、拉、摇过去。 代价是你得写代码,而且**(见下面「做不到什么」)。 颜色逐个从产品自己的 token 文件抄过来(_tokens.css / theme.css / tailwind config), 片子里不允许出现第二套。一支片子里混三条缓动曲线,观众读到的是三只手,不是一个产品的性格。 栏宽、字号、圆角、图标字重全按产品真实数值搭, —— 不是把 13px 的字放大成 20px 的示意图。图标重画产品同一套字形,不引第三方图标库。

README

promo-film

用代码做产品宣传片 / 推广片 / 演示短片。Remotion + React 出片 —— 片子里那台机器是按产品真实 数值重画的(或者 Playwright 抓的真机截图),全程进版本库,逐帧可复现。

一支片子在这里是一份可以编译的源码,不是一条时间线。每一帧画面都是「全局帧号」的纯函数:

export const B = {              // 节拍边界,帧(60fps)
  open: 0, files: 190, cli: 540, theme: 1000,
  push: 1400, cross: 1850, cta: 2150, end: 2420,
} as const;

export const state = (f: number): State => { /* 只读 f,返回这一帧窗口里的一切 */ };

文件树长出几行、agent 日志到第几条、指针在哪、主题插值到哪一帧 —— 全在 state(f) 里。 想重排节奏,改 B 里那几个数字,下游全部是相对量,动作跟着一起挪。 于是节奏能改、镜头能算、字能 diff,而且今天渲和三个月后渲逐字节一样。

如果你是 agent:要把它装进来 → 读下面的「安装」;已经装好、要拿它干活 → 读 SKILL.md,那是操作手册,references/ 是它按需展开的细节, 本文件只是说明书。

为什么不是剪辑软件

剪辑软件里,「把第三场缩短两秒」意味着手动拖后面每一个关键帧。截图配转场的那种片子, 观众读到的是「一堆图」,不是「有人在用这个软件」。

这里反过来:改一个数字,后面所有动作跟着挪,窗口全片不切镜,一台摄影机推、拉、摇过去。 代价是你得写代码,而且只能拍界面(见下面「做不到什么」)。

三条硬约束

先记住这三条,references/ 里所有细节都是它们的推论。

① 只有一套颜色、一套字体、一条缓动。 颜色逐个从产品自己的 token 文件抄过来(_tokens.css / theme.css / tailwind config), 片子里不允许出现第二套。一支片子里混三条缓动曲线,观众读到的是三只手,不是一个产品的性格。

② 那台机器是真的。 栏宽、字号、圆角、图标字重全按产品真实数值搭,按逻辑像素画完再整体缩放 —— 不是把 13px 的字放大成 20px 的示意图。图标重画产品同一套字形,不引第三方图标库。

③ 不做观众察觉不到的缓慢运动。 一个 270 帧涨 2.2% 的推近,折算下来每帧 0.005px:读不出是运镜,只看得出字在抖 (每帧按新的亚像素边界重新光栅化)。要让画面「活着」,用入场动画,不用缓慢缩放。

第三条是本 skill 唯一一个会毁掉整支片子、而且在时间轴上完全看不出来的坑。 references/camera.md 整篇都在讲怎么躲开它,动手改镜头之前先读那一篇。

配乐是可选的,而且默认不做

先问用户「这支片要不要配乐」,说要才做。 多数推广片在社交平台上是静音自动播放的, 信息本来就必须全在画面里;而配错了乐的推广片,比没配乐伤害大。 无声是一个完整的交付,不是半成品。

用户说要,本 skill 自带一个纯代码合成器(assets/scripts/lib/synth.mjs,452 行, 只用 Node 标准库):木质拨弦、有节奏的贝斯、沙锤、软底鼓、响指,外加一层压得很低的铺底。 没有采样、没有第三方素材、没有版权问题。里面没有随机数(噪声来自定种子的 LCG), 所以同一份配置永远产出逐字节相同的音频,配乐和片子一样能进版本库。

要点在 references/music.md:调性先定(第一节有一条明确的品牌禁忌)、 「涨」靠加声部不靠加音量、重音落在与剪辑相同的帧上。想用买来的曲子也行: 覆盖 public/bgm.mp3,长度对齐总时长即可。

用户说不要,工程里就不留任何配乐的痕迹 —— `` 那一层、music 脚本、 make-music.mjs、synth.mjs、public/bgm.mp3 全都不要。

安装

没有安装脚本。这个 skill 就是一份 SKILL.md + 六篇 references + 一批可以拷进工程的模板文件, 任何「能读文件 + 能跑 shell」的 agent 都能驱动。所以「装」只有两件事:把目录放到位, 让 agent 知道 SKILL.md 在哪。

有技能目录的客户端(Claude Code / Claude Desktop)放进约定目录就会被自动发现:

git clone https://github.com/whyubel1eve/promo-film-skill.git ~/.claude/skills/promo-film

跟着某个项目走、团队都能用:

git clone https://github.com/whyubel1eve/promo-film-skill.git .claude/skills/promo-film

目录名要用 promo-film,和 SKILL.md 里的 name 对上;仓库名叫 promo-film-skill 不影响。 自动发现靠的是 SKILL.md 顶部那段 YAML frontmatter(name / description), 客户端拿它判断什么时候该加载;不支持的客户端会把它当普通 Markdown 读,不影响使用。 装完要新开一个会话才认得到 —— 技能列表是会话启动时加载的。

其他客户端:放到那个客户端约定的位置,然后把下面这段抄进它启动时会读的配置文件:

产品宣传片 / 推广片 / 演示视频:要做片子、改片子的文案节奏镜头、出竖版时,
先读 /SKILL.md,按它说的做。片子用 Remotion 写代码出,不要去找模板或剪辑软件。
客户端 抄到哪
Codex CLI / 支持 AGENTS.md 的 项目根的 AGENTS.md,或 ~/.codex/AGENTS.md
Cursor .cursor/rules/promo-film.mdc
Windsurf .windsurfrules
只想临时用一次 哪都不用抄,直接在对话里说「读 /SKILL.md」

位置随你的客户端:文档之间全是相对引用,没有一处硬编码的绝对路径 (SKILL.md 里的 $SKILL 指克隆下来的这个目录),克隆到哪个目录都照样跑。 所以该由你客户端的约定决定,不该由这份 README 替你定。

依赖

skill 目录本身零依赖 —— 依赖是它生成的那个 video/ 工程要的:

  • Node.js ≥ 18
  • Remotion 4 + React 19 —— video/ 自己一份 package.json 和 node_modules, 不跟应用共用(Remotion 会拖进一整个 Chromium,应用不该为它变重)。 remotion 和 @remotion/* 必须同一个精确版本(不加 ^),混版本会在渲染时报奇怪的错。 装之前 npm view remotion version 看一眼,别照抄 references/setup.md 里的数字。
  • ffmpeg —— 抖动校验里裁窗口区域;配了乐的话还用它转 mp3。
  • Playwright(可选)—— 只有走「抓真机截图」那条路才需要。

skill 本身没有可以「跑一下验证」的东西 —— 装好的标志是你的 agent 认得出 promo-film 这个名字。不确定就直接让它读 SKILL.md,那份读得懂就是装好了。

从零到出片

搭工程 —— 照 references/setup.md,从 assets/ 拷现成的($SKILL 是你克隆到的目录):

mkdir -p video/src/lib video/src/components video/src/scenes video/scripts video/public
cp -r $SKILL/assets/src/lib/* video/src/lib/
cp $SKILL/assets/scripts/frames.mjs video/scripts/
cp $SKILL/assets/{remotion.config.ts,tsconfig.json} video/

配乐的那两份(synth.mjs / make-music.mjs)只在用户说要配乐时才拷,见 references/setup.md。

写 design.ts(抄产品 token)→ 窗口组件 → story.ts(节拍表 + 镜头表 + state)→ scenes/S*.tsx(只画文案,一行产品 UI 都不画),然后开 Studio 拖时间轴看动作和时序:

npm run dev

审构图 —— 批量出关键帧,比反复 render 快一个数量级:

SCALE=0.5 node scripts/frames.mjs 90 430 760 1290 1620 2050 2260

抖动校验 —— 停稳的两帧,窗口区域必须逐像素相同,改完镜头每次都要跑:

SCALE=1 node scripts/frames.mjs 460 461 462 463
cd out/frames && for f in 0460 0461 0462 0463; do ffmpeg -y -loglevel error -i Film-$f.png -vf "crop=600:400:1150:400" /tmp/k.png; md5 -q /tmp/k.png; done

四个哈希必须相同。这个 bug 在视频里看是「字有点毛」,在时间轴上看什么都正常, 只有这行命令能指认它。最后出片(npm run music 只在配了乐时才有):

npm run render && npm run render-square && npm run still

目录里有什么

文件 讲什么
SKILL.md 操作手册:三条硬约束 + 七步流程 + 出片前的收尾清单。agent 的入口
references/setup.md video/ 的目录结构、package.json、分层的 Film.tsx、竖版与方版怎么办
references/product.md design token 全部有出处、按逻辑像素画、图标重画、重画 vs 抓真机截图
references/camera.md 镜头表为什么不能写成关键帧轨道、改镜头要自己算的边界、运动模糊、三条禁令
references/story.md state(f) 怎么推、文案层的交接、每场多长、文案怎么写
references/review.md 批量出帧、抖动校验、半分辨率预览、十条毛病清单、发布前三问
references/music.md 只在要配乐时读:调性、「涨」靠加声部、两个调过的合成器坑、母带

assets/ 是拷进工程就能用的模板,一般不用改:

文件 是什么
src/lib/anim.ts 缓动词汇:t() / enter() / pop() / typed() / track(),两条全片通用曲线
src/lib/camera.ts 镜头表 → 摄影机:makeCamera() / stageTransform() / edges(),保持段自动生成
src/lib/scene.tsx 文案层的进退场交接(出去往上、进来从下,不叠双影)
scripts/frames.mjs 批量出关键帧:一次打包、一个浏览器、多张图
remotion.config.ts tsconfig.json CRF 15、jpeg 中间帧、120s delayRender 超时;strict TS
scripts/lib/synth.mjs ○ 只在配乐时拷,配乐引擎,452 行,无随机数
scripts/make-music.example.mjs ○ 只在配乐时拷,写「弹什么」的样板,拷成 make-music.mjs 改

做不到什么

  • 要真人出镜、要实拍素材 → 这是拍摄,不是渲染
  • 只是把现成视频剪一剪加个字幕 → 直接 ffmpeg,别搭工程
  • 只要一张图(封面 / OG 图)→ 那是静态图的活,别为它搭一个视频工程
  • 产品还没有稳定的视觉 token → 先把设计系统定下来,否则片子里那台机器是假的
  • 配乐只有一种编制(拨弦 / 电钢 / 铺底 / 贝斯 / 轻打击)→ 要人声、管弦、失真吉他、 EDM,去买授权,覆盖 public/bgm.mp3 就行,别用合成器硬凑
  • 9:16 竖版不是免费的:1:1 可以把内容层整体缩到 0.62(只缩内容层,背景保持满幅), 但竖版的「左边一句话、右边一台机器」必须改成上下堆叠,镜头表的 cx/cy 要另写一份。 要做就当第二支片子的排版工作量估。

授权

代码按 MIT 授权。

assets/ 里的模板可以直接拷进你自己的工程改,不用署名。配乐引擎产出的音频是从零算出来的, 不含任何第三方采样或曲库素材 —— 商用、改编都可以。(这说的是本仓库产出的东西。 你自己往片子里放的字体、图标、截图,权利归属还是得你自己确认。)

收尾清单

出片前逐条过,任一条不过就别发:

  • [ ] 停稳段落里,窗口区域逐像素帧帧相同
  • [ ] 文案没有压在窗口上:算过 cx - px·k 和 cx + (shellW - px)·k
  • [ ] 摄影机到位之后文案才进场
  • [ ] 每一场最后一件事做完之后留 0.7~1.3 秒收口,不留第二秒
  • [ ] 全片只有一套颜色、一条缓动;片里的数字(体积、版本、域名)跟真实产品对得上
  • [ ] 要不要配乐问过用户了;配了的话重音与节拍起始帧对齐,改过节奏就重新 npm run music
  • [ ] 静音播放看不看得懂 —— 信息必须全在画面里,配乐(如果有)只负责情绪
  • [ ] video/README.md 写清楚「想改什么去改哪个文件」、这支片子已经讲过什么、 以及踩过的坑(原样保留,别删 —— 删掉的坑三个月后会原样再踩一次)

最后一条不是客套:下一个改这支片子的大概率还是个 agent,它只会读那一份。

在 GitHub 查看完整 README

推荐工具

换一个关键词,或者移除筛选条件。

安装

npx skillfish add whyubel1eve/promo-film-skill
新手?先看 mcpskill.org 教程 →