Skip to content
FunCoding

Search

Search docs, Skills and MCP

video-talkcraft

终极口播视频 skill:中文口播稿 + 成品配音 → CPU 字级时间戳 → SHOTBOOK 层矩阵分镜 → Remotion 电影感成片(横屏默认/竖屏)。当用户要"做口播视频"、"解说/科普视频"、"把文案变成视频"、"给配音配画面动效"时使用。默认使用成品配音,可选 Fish Audio 从稿子合成配音与时间戳;数字人生成技术不在本 skill 内(人物素材是输入)。含统一视觉语言(Apple 范式)、108 张动效配方卡、镜头三面分层工作单、七层镜头反PPT系统(极缓推拉相机/让位,运动做减法)、六式运动承接转场(每式一卡)、长镜头世界画布、anime.js+three.js 桥、自动静止检测 + 独立 subagent 评估循环。

AI 与智能体1.4kSKILL.md

Install

Send this to Claude Code, Codex or Cursor. The agent checks the Skill for safety first and installs it only after you confirm.

读取 https://funcoding.ai/skills/vincentwei1021/video-talkcraft/video-talkcraft/install.md ,按里面的步骤帮我安装这个 Skill。

SKILL.md

video-talkcraft — 口播视频 skill

三大来源合体:管线(配音→字级时间戳→Remotion)+ 词汇(108 张动效配方卡,全配可播 demo + 自包含 tsx)+ 镜头(七层模型反 PPT 系统)+ 视觉语言(Apple 范式默认版)。

核心范式:解说词驱动画面,每句都要有活的画面响应(相机极缓推拉/已有元素的变化), 但新元素只在语义拍边界进场,禁止机械的"一句一个新元素"(一句一元素是堆积型凌乱的制度根源; 分镜按语义段落切,排版预算见 cinematography.md §4.5); 一个节拍只有一个主角,说完就让位;字幕句边界 = 全片时间锚点。

流程

① 文案 → ② 配音输入+时间戳(本机CPU) → ③ 素材 → ④ SHOTBOOK 层矩阵 → ⑤ 实现(全局系统 → 首镜先做先确认 → 其余镜头)
                                → ⑥ 渲染 → ⑦ 三重验收(机器闸全过 + 1 轮审片修 P0/P1)→ ⑧ 交付(可选续审 ≤3 轮)

⓪ 开工体检:统一依赖 + 画幅与视觉语言

依赖只有一份:所有口播工程的 remotion/node_modules 与 workbench/node_modules 都是指向 <skill根>/runtime/node_modules 的软链,版本只在 runtime/package.json 里钉(@remotion/* 全家同号)。新片开工第一件事(用户 2026-09-15 定版:每次新做视频都要检查更新):

bash <skill根>/runtime/check-runtime.sh --upgrade   # 装好共享依赖 + 共享无头浏览器 + 链好 workbench;Remotion 有新版就全家升级并冒烟渲 1 帧,不过自动回滚

末行 [runtime] OK 才往下走;升了级要把 runtime/package.json / package-lock.json 的改动提交。制作中途不升级(母版段缓存不认依赖版本,混版本渲出的段不一致)。 工程目录里永远不跑 npm install(会写进共享目录);要加包 → 加进 runtime/package.json,npm ci,再提交。

画幅与视觉语言(开工先定,全流程引用)

  • 画幅默认横屏 1920×1080(用户偏好);明确要发抖音/竖屏渠道才用 1080×1920
  • 视觉语言:用户明确点了风格就按用户的来(整套 token 替换);没点时先从口播稿判定领域、派生本片风格档 (references/design-language.md §0:读全稿答"讲什么 / 对谁讲 / 什么口吻"→ 领域 → 风格档表给底色策略 / accent / 字体气质 / 材质与卡造型 / 图表语言 / 素材气质 / 能量档, 写进 SHOTBOOK §0 G0 风格档),骨架仍是 Apple 范式(一个强调色/一个投影/底色交替分幕/两档字重/ 默认幕底:浅 pastel-mesh-flow / 深 mesh-flow-dark——12 款幕底见 §1.1,代码 template/motion-systems/backdrop.tsx), 派生本片 token 落成 theme.ts。对任何风格都成立的只有一条:禁止逐场景随手取色。 卡是中性 UI,进片必须蒙皮:动效卡的 demo / tsx 是无风格的中性呈现,复制进工程后按风格档改皮(颜色 / 字体 / 圆角 / 材质 / 图表坐标轴与标记 / 占位图形)、 不改运动命门(时序 / 缓动 / 几何比例 / 层级),契约与反例见 design-language §0.4;SHOTBOOK 每镜写蒙皮行

① 口播稿

  • 每句一个信息点,钩子在第一句(数字/冲突);13 句 ≈ 95s
  • 数字一律汉字(时间戳按文本逐字锚定,197747 无法与"十九万七千"的读音对位);英文品牌词直接写(中英混合对齐已验证)
  • 先调研核实事实,列"事实红线清单"(不可说错的数字/未验证数据不引用)

② 配音输入 → 预剪 → 字级时间戳(默认本机 CPU;可选 Fish Audio)

默认使用成品配音:真人录音或任何 TTS 皆可,输入 = 一条完整配音(wav/mp3)+ 与之逐字一致的口播稿。 没有录音且用户选择合成时,可使用下面方案 B;它不会替换已有配音或默认的本机 CPU 流程。

②-0 配音预剪(真人录音必做;TTS 只会压气口,可跳过)——剪掉口水词(嗯 / 呃 / 那个…)、结巴重说、过长停顿, 在做时间戳之前跑(时间戳做完再动音频 = timing / beats 全体错位;预剪 → 时间戳 → 一切后续,顺序不可换):

python3 scripts/voice_trim.py audio/raw.wav script.json --dry-run --words-out audio/asr_words.json   # 先只出报告:逐条 [filler / repeat / pause] 起止 + 共剪多少;ASR 结果落盘
python3 scripts/voice_trim.py audio/raw.wav script.json --words audio/asr_words.json --out audio/full.wav \
    [--video dh/host_raw.mp4 --video-out dh/host.mp4]               # 用户认可后落盘(吃回上一步的词表,不再跑一次 ASR);同一条录音的人物视频用同一 EDL 剪(音画逐帧同长)
  • 稿子是真值,宁漏勿错:只剪 ASR 里稿子没有的插入段——全由口水词表拼成的(filler)、等于紧邻稿文的结巴 / 重说(repeat); ASR 听错稿子里的字永不剪(剪它就剪掉了那个字的真实发音);稿外改了措辞的重说只报告,--cut-unmatched 才剪。 词表来源缺省跑 FireRed(与下面时间戳同一后端),也吃剪映等导出的逐字 SRT(--srt)或词级 JSON(--words); 句级 SRT 定位不到口水词,脚本会警告。无稿时只剪整 token 文字恰为保守词表(嗯 / 呃 / 额 / um…)的口水词——按规范化文字精确比对、不认同音(五≠唔、饿≠呃); 紧邻重复的短词无稿只报告不剪(逐字 token 下分不清叠词与结巴)。剪同录的透明 webm 时会解一帧核 alpha,帧数对但透明丢了也算 FAIL。
  • 停顿:≥0.7s 的静音压到 0.35s(留段内最安静的一窗真实房间音,不补数字零),首尾留白 0.25 / 0.5s; 切点先找能量谷、再吸附 30fps 帧网格;cuts.json 是 EDL(含源 → 新时间轴映射表,剪人物视频与后续任何对账都吃它)。
  • dry-run 报告必须给用户过目再落盘:标了「切点未落在静音里,听一下」的条目让用户听那一处;脚本只删不合成,不改语速不改音高。 剪完人物视频后跑 ③ 的 preflight.py --media-only 核时长——同一 EDL 只对同一条录音成立。

字级时间戳(对预剪后的 audio/full.wav):

# 方案 A(已有录音,本机 CPU 对齐):
pip install zhconv pypinyin sherpa-onnx soundfile numpy   # 默认后端 FireRedASR2-CTC int8 的全部依赖
# 首次:下载模型 767MB(model.int8.onnx + tokens.txt)放 ~/.cache/koubo/<模型名>/,地址见脚本头注释
python3 scripts/timestamps_cpu.py audio/full.wav script.json audio/timestamps.json
# 备选(免手动下模型):pip install faster-whisper 后加 --backend whisper(首跑自动下载 460MB)
python3 scripts/make_timing.py audio/timestamps.json remotion/src/timing.json

# 方案 B(可选生成配音 + 时间戳,默认请求 s2.1-pro-free;可用性以 Fish Audio 为准):
pip install requests python-dotenv   # 还需 ffmpeg,生成前会检查
# 在 .env 配置 FISH_AUDIO_API_KEY=xxx 及可选 FISH_AUDIO_REFERENCE_ID=xxx(见 .env.example)
python3 scripts/tts_fishaudio.py script.json audio/full.wav audio/timestamps.json --timing-out remotion/src/timing.json
  • tts_fishaudio.py:默认 --mode sentence 每句一次请求,插入 --pause-sec 指定的真实静音(默认 0.25 秒);--mode stream 整稿一次请求、保留自然停顿。两者均接收 UTF-8 SSE,生成结束才写文件,不提供流式播放。先解码 PCM 再拼接,偏移按采样数计算。空音频、缺失/无效对齐或文本不匹配时报错;只忽略标点、大小写与字符宽度,不自动转换数字读法。中文用接口字级锚点,英文词内插值;match/ok 仅确认文本映射,仍需试听。合成后若再预剪,须重新运行 CPU 对齐。
  • timestamps_cpu.py:ASR 词级时间戳 → 与口播稿字符级对齐(CJK 是可靠锚点, 匹配键=繁简归一+无声调拼音,同音字不算错;拉丁词各家 ASR 都常拼错,在锚点间插值)→ 每句 match 质检,<0.90 标出人工听核。默认后端 FireRedASR2-CTC(尾部最稳、零误报;整段喂入 ~200s 崩、内存平方涨,脚本默认按静音切 ≤75s 段再加回偏移,--chunk-sec 可调),备选 faster-whisper; 各后端横评数据与模型下载地址见脚本头注释。
  • timestamps.json schema:{sr, total, sentences:[{i,text,start,end,match,ok,words:[{text,start,end}]}]} ——words 为 CJK 逐字 + 拉丁整段 token(标点跳过);满足此 schema 的任何对齐工具都可替换。
  • make_timing.py:转成 timing.json(chars 与文本逐字符 1:1,标点零时长),供 tSay/msSay 锚点查询
  • 配音自查(耳听):无爆音/截断/误读;句间留 ~0.3s 气口,时间锚点更稳

②-1 语义标注(2026-09-22 起必做,正主 references/semantic-annotation.md)

口播稿逐句标「这句在做什么」,落成工程根 semantics.json——这是选卡的需求侧产物,没有它,选卡只剩输入类型一道过滤、剩下几十张卡靠印象挑(2026-09-21 那支片的「我是万里」就这样拿到了全库能量最低的文字卡,库里 P0 的人名条没人查到)。

python3 <skill根>/scripts/semantic_annotate.py --init     # 从 timestamps.json 出骨架(带词法提示 hint)
#   逐句填 sem(26 词封闭词表,见 taxonomy.md「语义索引」)/ weight(main 主句 = 允许进新元素、sub 陪衬句)/ entities / need
python3 <skill根>/scripts/semantic_annotate.py --stats    # 校验:与时间戳逐字一致 · 词表封闭 · 词法硬规(我是X→自我介绍、点赞订阅→号召、数量词→数据)· 每镜至少一个 main

标注是派生物:预剪 → 时间戳 → 标注 → 其后一切;改稿或重剪后 text 对不上就是标注失效,重新 --init。 ②-1 早于分镜,所以 shot 字段此时是空的(SHOTBOOK 还没写):④ 写完后必须回填一次,否则下游的镜头级覆盖核不到任何东西——

python3 <skill根>/scripts/semantic_annotate.py --sync-shots   # ④ 之后:按 SHOTBOOK 标题的起止秒(或 shots.json)回填 shot,只动 shot,标注不丢

③ 素材

  • 素材清单从 ②-1 的语义标注生成,不靠拍脑袋:need 是 证据 的句去截真页 / 找出处,身份 要头像与账号信息,量化 要图表或数据源,entities 里的人名 / 品牌 / 地点 / URL 就是检索词。
  • 先给每个镜头标素材模式(多选,可组合):B-roll(实拍视频)/ 图片(照片 / 海报 / 插图)/ 截图(网页 / 界面证据画面)/ 纯动效——如"B-roll 打底 + 截图证据卡"。新闻/信息类话题证据优先:Playwright 实时截图比泛用 B-roll 更有信息量。 四档对应 taxonomy.md 输入类型代号 V / 图 / 截图 / 文,SHOTBOOK 每镜写一行 素材:V(路径)· 图(路径)· 文(格式见 ④)
  • 实拍素材是必需项,不是可选项(2026-09-06 硬规):全片零 B-roll / 图片 = 只有动效 + 口播人物 = 观众看到的是"讲 PPT"。 preflight.py 对账 SHOTBOOK:零 V / 图 镜头直接 FAIL,V / 图 镜头占比 < 1/3 WARN(要在 SHOTBOOK 给依据,如证据类题材以截图为主)。 「本片不做 B-roll」不允许写成设计决定;视频源搜不到就降级图片(Pexels photos 原图 → Pixabay),图片也没有才进「未完成 / 未采集清单」。 图片与视频同源同 key,采集规格(分辨率下限、落盘目录、登记)见 references/broll-sources.md「配图采集」
  • 真图硬规:话题存在可截的真实页面(产品官网/GitHub/文档/画廊)时, 成片中的浏览器/页面类镜头禁止用代码 mock 冒充截图——卡片 demo 里的灰条假 UI 是占位物, 成片必须按卡片"复用指引"整块换成 <img> 真图;mock 只允许表现无真实对应物的示意 UI, 且 SHOTBOOK 逐镜标注"为何无真图"。引申:口播讲"这样的成片/效果"时, 示例画面必须是真成片片段(<OffthreadVideo> 内嵌已有成片/真机内录裁切,muted); 讲"长页面/看板/参数页"时用 Playwright 全页长截图(放大镜/巡航类动效直接吃真图坐标)。 真图上的标注坐标一律机器实测,禁目测:页面元素用 DOM getBoundingClientRect、成图用逐像素量测 (目测偏 ±30px 就会把环框到别的元素上);会滚动/移动的真图,标注(环/框/pill)必须钉在内容坐标系上随内容动, 钉屏幕固定位就是错位根源
  • 单视频镜头要有主题边框(2026-09-07 用户定版):镜头里唯一主体是一段视频(录屏 / 单条 B-roll / 引用别人的成片或采访)时, 禁止裸贴满幅、禁止裸放白卡、也不装假播放器(进度条 / 播放键 / 时间码一律不要——不是真播放器就是在撒谎),视频区必须包一层 template/components/theme-frame.tsx 的 <ThemeFrame kind>:八式(复古浏览器窗口 / 杂志相框 / 35mm 胶片 / 拍立得 / 工程图纸 / 笔记本 / 邮票齿边 / 双发丝线), 按片子调性选一式、一片只用一式,写进 SHOTBOOK 蒙皮行;多视频的卡(bed-echo-blur 前景 / split-60-40-story 左格 / gallery-wall-dolly)的视频区也包同一式。 框只管造型与自己的装饰接力,整体入场 / 退场 / 极缓推归镜头层;框里的画面零处理(不滤镜 / 不缩放 / 不淡入淡出)。 例外只有两种:视频当底床不当主体(bed-echo-blur / §1.2 实拍底床),以及产品界面卡(chat-gpt / claude-code 类,皮即内容)。 静图不进框(框说"这是录像",画面不动一眼假;图用 media-pop-in / slow-push-in)。规则与八式表:design-language §1.3
  • 网页拍摄不贴图:找资料/找素材时判定可用的网页,成片里禁止以静态截图贴屏, 必须像手持镜头一样"拍"它——滚(evidence-scroll-tour◆:匀速上滚 ≈10% 页高/s,讲到关键条提前减速停 1~2s)/ 巡(stage-keyframe-tour◇:长页躺台上不动,相机挨个停靠兴趣点)/ 放大(magnifier-detail 圆形放大镜 看一眼就撤,pip-zoom-box◈ 拎出来长期挂着)/ 划(highlighter-sweep 扫整句、ink-underline◇ 划一个词、 scribble-annotation 圈注箭头、corner-bracket-frame◈ 框区域);一屏装完的页面至少走 slow-push-in 底噪。 一镜一主式:滚动/巡游段内不弹放大镜、不现场划线,顺序是「滚到 → 停 → 划/放大 → 再滚」; 拍法选型表见 shot-design.md §2④「网页拍摄」。素材按 broll-sources.md「网页拍摄素材采集」规格落盘: Playwright 全页 2× 长截图 + 同一会话 DOM 实测的目标坐标 JSON(放大镜/划线/停点全吃这份坐标,接上一条"禁目测")。 拍摄一律由 Remotion 在长截图上完成(seek-safe、可对词锚),不用浏览器录屏(帧率不稳、懒加载与粘性头穿帮、 对不上字级时间戳)。唯一放行:一屏装得下且只当配角(media-pop-in 多张堆叠里的一张)的小截图可静态入卡, 但仍带 Ken Burns,不得是该拍主体
  • 标了 B-roll 的镜头列 2–3 个英文视觉概念词跑 Pexels + Pixabay API 双源并行,候选落 assets/broll/; 源分层与授权红线(只用免署名源)见 references/broll-sources.md
  • 调研记账:承载关键事实的来源页逐一截图存档,sources.md 里链接与本地截图一一对应 (禁止只存链接不留证据);成片引用时优先用存档截图当画面证据 + micro 阶来源行
  • 有 B-roll/截图 + 对应口播的人物素材(录播/数字人成品)时,人物一律降级成角标常驻—— 圆形头像章(host-shrink-to-chip◆)或抠人贴角,落左下 / 右下角;不许切走人、不许人物占满画幅。 两路选型与全部硬约束以 references/host-footage.md §5 为准,镜头预设见 shot-design.md §2⑦
  • Manim 图表:--transparent --format=mov 后必转 VP9 webm(-c:v libvpx-vp9 -pix_fmt yuva420p)
  • 全部落盘 public/,禁止渲染时拉远程
  • ③ 收尾必跑素材体检(把 host-footage / broll-sources 里的入场硬规变成断言;答案早就写在 reference 里、但没人在正确时刻去查, 是 2026-09-06 复盘里两个最大的坑的共同失效模式——所以不再补文档,改成开工前必跑):
python3 scripts/preflight.py --media-only --host remotion/public/dh/host.webm --fps 30 --voice audio/full.wav
# 查:人物素材 r/avg 帧率一致(VFR)· 源片无重复帧签名 · 素材 fps = 成片 fps(不等→成片改成素材 fps,禁 -r 直转)·
#     时长与配音逐帧对齐 · 真实宽高比 · 素材盘点(实拍/图片/网页长图数)· sources.md 在册。任一 FAIL 不进 ④

④ SHOTBOOK(必产出,实现前评审)

先用 references/shot-design.md 给每个镜头填三面分层工作单(背景面/主体面/文字面 + 各面动效

  • 七种镜头类型预设),再按 references/cinematography.md §4 展开成层矩阵,范例 references/shotbook-example.md。 每场景:一句意图 + 主体接力线 + 逐节拍层矩阵(节拍锚定字级时间戳;每行动作必须答得出"配合谁")。 每镜必写「素材:」行(机器可读,preflight 逐个 stat 文件):- 素材:V(public/broll/gpu.mp4)· 图(public/stills/a.jpg, public/stills/b.jpg)· 截图(public/pages/gh/page.png)· 文—— V / 图 / 截图 必须括号给路径,写"待采"= FAIL;纯动效镜也要写 素材:文。 必填「## 未完成 / 未采集清单」节:任何"本片不做 X"二选一——归入 §0 的设计决定(+依据),或归入本节(+阻塞原因 + 兜底源是否试过); 允许写"无",不允许缺节。这一节专门拦"未完成被包装成设计原则、进而变成不再被质疑的前提"(2026-09-06 复盘的真正失效模式)。 G0 写一行「样板镜:sNN」(⑤-1 首镜先做先确认用):默认 s01;s01 是章节卡 / 空镜等不带主体动效的镜头时,选第一个有卡、有字幕、有人物或素材的镜头。 节拍必须机器可验:每条画面重音落成 remotion/beats.json ({t, anchor, sentence, what},t 一律由 timing.json/atChar() 查得,禁止手敲近似秒数—— 手敲的误差静帧 QA 看不出来),SHOTBOOK 节拍表与 beats.json 一致, 机器闸用 scripts/beat_lint.py 对 timestamps.json 校验 |Δ|≤0.1s。 未到拍不显形:词锚未到的数字/图形必须完全不可见(opacity 0), 禁止压暗/灰显"预告";行内数字要连同其后继字符一起 gate(「就 __ 类」的空洞挂着同样是缺陷)。 开镜不空台:镜头开场到第一个动效锚点 >1.5s 的空窗必须有承载画面 (真实 b-roll / 上一镜元素延续 / 真素材墙),不许空画布干等词锚。 镜尾保护带:词锚动效落点距镜头出点 <0.7s 的,要么提前、要么挪进下一镜——落点会被转场吞掉; beat_lint.py --shots shots.json 机器查 ≥0.5s 硬底线。 幕级转场事件同样入 beats.json:shape wipe/换幕的遮挡峰值时刻也由词锚生成入表—— 手敲绝对秒的转场事件表游离在机器可验体系外,静帧 QA 与 beat_lint 都看不见。 排版预算(全表 cinematography.md §4.5):分镜按语义段落切、每镜一个 primary visual job; 纯文镜必配陪衬图形(2026-09-07 用户反馈"只有文字动效往上堆太单一"):素材行只有「文」的镜头(章节卡除外),层矩阵必须多一行 「G5 线稿示意图 ← 讲 X 所以画 Y」(references/schematic.md,代码 template/motion-systems/schematic.tsx),preflight 对缺行的纯文镜 WARN; 枢轴句("但这次不是X"式转折/设问)的动效归它开启的下一镜;任一时刻同屏主体组 ≤3(降权留守计入)、 每镜至少留一个空象限;hero 造型一屏一个。 排版规范(全表 references/layout.md):预算管"放多少",规范管"放哪、多大、怎么对齐"—— SHOTBOOK 每镜写版式行(栏跨度 + 组包围盒 + 对齐基准 + 字阶),定妆帧开 debugOverlay 核九项,任一失败 = P1; 独句 hero 居中但不得覆盖人脸(含 B-roll 里的人脸,纵向改取人脸之外的三分线)。 版式轮换(2026-09-21 用户:成片"人物在左下角、素材在中间方块、右边放文字,过于固定";全表 cinematography.md §4.5 第 9 条):写逐镜矩阵之前先在 G0 写「版式节奏表」 (| 镜 | 人物形态·方位 | 素材容器 | 主卡 |,格式 cinematography.md §4)——同一张呈现卡(素材呈现 / 数据 / 运镜类)不连用 3 镜、全片 ≤1/3(≥6 镜的片);人物形态(半身 / 角标左下 / 角标右下 / 分屏格内 / 抠人贴角 / 短暂离场) 与素材容器(出血全屏 / 装框 / 分屏格 / 底床 / 多图编排 / 3D 墙 / 长页)连续 3 镜至少换其一;同一条 B-roll 不进相邻两镜。单条 B-roll 按 shot-design.md §2⑦ 七式选、相邻镜不同式, 多素材按 §2④′ 关系表;preflight 按节奏表 + 蒙皮行核(连用 / 占比 FAIL)。轮换是换构图不是加运动——每式内部仍只有相机极缓推拉。 每镜必写「选卡行」(②-1 的语义 → 卡;候选由机器给):
python3 <skill根>/scripts/card_match.py --out qa/card-candidates.md   # 语义 × 素材行 × 卡索引 → 每镜每个主句语义的可行候选 + 排序理由 + 落选理由

跑之前先 semantic_annotate.py --sync-shots 回填 shot(②-1 时还没有分镜)。候选表除按语义列候选,还会给声明了素材的镜单列一行 素材承接候选——声明了 V / 图 / 截图 却没有呈现 / 运镜类卡承接 = 素材裸贴,preflight 判 FAIL。 SHOTBOOK 每镜写 - 选卡行:<语义> → <卡>、<语义> → <卡>(选卡行里的卡要真的落进蒙皮行,preflight 对账); 选候选之外的卡要在该镜写一行 - 语义偏离:自我介绍 ← 开场已报身份,s11 不再重复(理由 ≥4 字,preflight 认这行放行)。 层矩阵的节拍行加一列语义(值取自 semantics.json,不另造词),这样「这一拍在做什么」在分镜里就是机器可读的。 选卡必读卡经验:每张选中的卡,把 references/cards/<slug>.md 的「已知坑」与「落位自检」逐条抄进该镜层矩阵的自检列, 实现后按条核(例:取景框 / 圈注 / 下划线类卡必核标注是否套住目标;gooey-morph 只用于图不用于字且无人物时居中;chapter-title-card 每章一套主题色 + 一个与本章内容相关的线稿 motif,SHOTBOOK 写章节主题行——四张同色同纹样的章节卡是"又来了"不是"翻页")—— 卡经验不进 SHOTBOOK 就等于没读。 动效词汇从 108 张配方卡 里选,两道过滤都查 references/taxonomy.md 的机器生成索引(源头是各卡 frontmatter 的「输入 / 语义 / 素材形态 / 位置 / props」五个字段,scripts/cards_index.py --write 生成、--check 校验,手改索引无效):先按这一镜的输入过滤(人 / V / 图 / 截图 / 文 / 界 / 场——「输入类型索引」),再按这句口播的语义过滤(自我介绍 / 数据 / 对比 / 列举 / 引用 / 号召……26 词封闭词表——「语义索引」,一张卡只列在它专为之而设的语义下);索引里带 ◦ 的卡没有可换内容的 prop(只暴露资源 / 皮肤类,或什么都不暴露),改文案 / 数据要动 tsx(各卡复用指引的 props 行写了改哪里)。◉◎ 两批新卡(29 张)md 开头另有「输入类型」表 + 「常用场景」四条。然后 references/taxonomy.md 分类索引 → references/cards/<slug>.md 参数与坑 → template/cards/<slug>.tsx 自包含 Remotion 源码(实现以它为准,复制进工程改 CONFIG 即用);demos/<slug>/index.html 是同画面的 HTML 预览(open gallery/index.html 一屏浏览、demo 滚入即自动播放;带★实战卡的生产母本另在 template/motion-systems|components)。 保真铁律:每张用到的卡在工程里必须真实存在 src/cards/<slug>.tsx (自 template 复制改 CONFIG)——只读 md 就凭卡名手写"神似"简化版是最大翻车源 (回弹/拍击/密度全丢、取景框括号方向画反、名片变色块),机器闸用 scripts/card_lint.py 逐 slug 校验存在性与相似度(≥0.55,改 CONFIG/文案在容忍内)。 蒙皮不是重写:复制来的卡是中性 UI,必须按 SHOTBOOK §0 风格档改皮——颜色全换 theme token、字体栈与字重、圆角 / 描边 / 投影 / 材质、 图表卡的坐标轴 / 网格 / 标记 / 数字字体、卡片类的占位图形换真素材或风格化图形——只改皮层,不改时序 / 缓动 / 几何比例 / 层级; 每镜层矩阵旁写蒙皮行(卡名 → 改了什么皮),同一片内同类卡共用一套皮;契约、例外(产品界面卡不蒙皮、语义色不换色相)与反例见 design-language §0.4。 card_lint 的 0.55 就是给蒙皮留的余量:改皮过得了,重写运动才掉下去。 三段式铁律:入场 0.20.8s → hold(静置即可——画面的活由场景相机极缓推拉负责)→ 出场 0.150.5s;入场永远比出场用力;同屏重音同一时刻只能有一个。 选了动效就要带上它的音效:每张卡在 demos/_lib/sfx-map.js 有 cue 表({t, name, vol, rate?, clip?},t 为卡内相对秒)—— SHOTBOOK 选卡时把 cue 抄进该镜头的层矩阵(换算成绝对秒;vol 按成片口径重标 ≤0.35, demo 库的 0.65 上限是试听口径不是成片口径)。实现时按 ⑤ 的 sfx 步骤落地。 覆盖口径:主要动效入场全覆盖,对齐 demo 库密度 (每卡 26 记 ≈ 0.4 记/s,100s 的片约 4050 记)——"少而准"管的是单点不叠双记、 音量克制(≤0.35)、连续揭示类(缓拉/对焦/逐字升起)与金句纯文字卡、logo 落幕留白、 转场只配蓄势不配落点、不要收尾叮当与重砸;不是砍覆盖面。真采样(pk- 前缀)优先。 cue 的 file 名以 ls public/sfx/ 为准(pk: 键名里的冒号导出成 pk-, 个别键自带前缀会出现 pk-transition-transition-soft 这类双段名——名字错了渲染直接 404 失败)。

④→⑤ 闸:SHOTBOOK 写完先过 preflight 全量,再进实现(③ 的素材体检 + SHOTBOOK 对账,任一 FAIL 挡住 ⑤):

python3 scripts/preflight.py --shotbook SHOTBOOK.md --host remotion/public/dh/host.webm --fps 30 --voice audio/full.wav --shots remotion/shots.json --semantics semantics.json
# SHOTBOOK 对账:每镜有「素材:」行 · V/图/截图 的文件都在盘上 · 零 V/图 镜头 FAIL · 占比 <1/3 WARN · 「未完成 / 未采集清单」节在册 · shots.json 与镜头 id 一致
#           · 版式轮换:同卡连用 ≥3 镜 / 呈现卡 >1/3 / 节奏表连续 3 镜同形态同容器 FAIL;版式行复制 / 素材相邻复用 / 缺节奏表 WARN

⑤ 实现(Remotion)

先装全局系统再写场景(代码 template/motion-systems/,规范正主 cinematography.md §2,运动做减法): 只装 G1 CameraRig(每场景一条极缓推进或拉出的 scale 曲线,1.00→1.04~1.06 或反向,不做 x/y/旋转/模糊,impulses 留空,shots.ts 表驱动) 与 G3 让位状态机(Live demoteAt = 下一主体锚点 / Defocus,idle 关、落定即静置;demoteAt 是降权留守不是退场—— 元素压暗缩小后仍占着原槽、计入同屏预算,新主体不得摆进它的位置;旧名 retireAt 仍可用但已 deprecated,2026-09-06 因名字误导出过 P0 文字相撞); G2 视差、G4 分幕色温可选、默认不装;主体 idle / 环境呼吸 vignette / 扫光 / 曝光脉冲 / 相机脉冲一律不做。 G5 线稿示意图(schematic.tsx + icons.ts)只给纯文镜装:DrawPath / DrawIcon / Connector / Node / Plate / Panel / Cross / Tick / Traveller / Label, 全部 abs 秒驱动、机器一笔画、线到哪亮哪、一套皮;图标缺什么跑 python3 scripts/fetch_icons.py <slug,...> --merge --out <工程里 icons.ts 的路径>(不带 --out 写的是库内 template/motion-systems/icons.ts;Iconify lucide = ISC + 部分 Feather MIT,根目录 THIRD_PARTY_NOTICES.md 随 icons.ts 一起拷进工程并登记进 sources.md)。

每个镜头边界必须有明确转场处置,禁止裸切:运动承接六式(lead/tail 重叠 12–16 帧 + ShotFade, 代码 template/motion-systems/transitions.tsx)或 caret/shape-wipe 轻量式,选型见 cinematography.md §3; 一个边界只用一式。空间/流程叙事段落可改用长镜头世界画布(longtake.tsx,cinematography.md §3.5)。 template/components/ 是即取即用件:Subtitles 整句硬现版(chunks 由 props 注入)/FlowerWord 花字/SmashWord 砸字/HighlightSweep 荧光笔/PencilDraw 铅笔手绘/Mascot 吉祥物/NumberRoll。 底部字幕:素排、无标点(正主 design-language.md §5):跟读字幕不加任何动效、整句硬现,不含任何句读(数字/型号间的半角点号除外,停顿靠拆卡); 唯一例外 keyword-pop-highlight 关键词弹出且全片 ≤3 次(motion-systems 版 keywords prop 有此上限自检)。 音效落地:node scripts/sfx_dump.mjs remotion/public/sfx 把库里采样解码成 mp3 → SHOTBOOK 抄来的 cue 表落成一张 sfx.ts(绝对秒),场景里 <Audio src={staticFile(...)} startFrom/volume> 逐条摆; 音效电平比人声低 ~12dB、同帧最多一条 cue。 anime.js v4 / three.js 走 anime-remotion.ts / three-anime.ts 桥(seek-safe,工程铁律见 cinematography.md §6:零 Math.random、初始 opacity:0、lead 补偿收敛一处)。

⑤-1 首镜先做先确认(2026-09-09 用户定版——其余镜头动工前的必经关)

不再"整片做完再看第一镜":全片共性(蒙皮 / 字幕样式 / 相机幅度 / 卡的密度 / 音效电平)在一镜上就判得出,做完 13 镜再改是 13 倍返工; "改一行就整渲"的冲动也集中在这一段(2026-09-08 issue #24:9 次整片直渲全发生在制作完、验收前)。

  1. 先搭全合成骨架:remotion/ 目录建好后先 bash <skill根>/runtime/link-runtime.sh <本片工程>(node_modules 软链到统一依赖、package.json 依赖版本抄 runtime——不自建、不 npm install), 然后 entry / 全片时长 / shots.ts + shots.json 全表(时间来自 SHOTBOOK 与 timestamps,此时就写全)/ 全局系统(G1 相机、G3 让位、幕底、字幕、theme) / src/sfx.ts 先建成空表(export const CUES: SfxCue[] = [])——⑤-2 拆解契约的六个文件(shots / scenes/index / Subtitles / sfx / timing / camera)骨架期就要齐, 工作台一接入就是多轨、之后每落一条 cue 轨上就多一块;缺 sfx.ts 进不了多轨、工作台右下角会点名缺哪个契约模块(@kbsrc/* 真实 / stub 的别名在 dev server 启动时定,后补文件要重跑 link-project.sh 并重启); 其余镜头一律占位——MainVideo-example.tsx 里 SCENES[shot.id] 查不到就落到 PlaceholderScene(只露幕底 + 字幕,不写任何动效)。 骨架搭全是为了 render_shots 的段表 / 时长断言原样生效,不为首镜开豁免。
  2. 只实现样板镜(SHOTBOOK G0「样板镜」行,默认 s01):按 SHOTBOOK 全量落地——蒙皮行、卡 tsx 复制、音效 cue、转场处置——不做"先糙后精"。
  3. 渲一条有声单镜预览给用户看:只渲这一段的视频和这一段的音频,不渲整条音轨(其余镜头都是占位,整条音轨没意义;2026-09-09 demo v4 实测 6s 首镜 47s 出预览:段 34s + 段音频 10s):
# 在工程 remotion/ 目录下
node <skill根>/scripts/render_shots.mjs --shots shots.json --only s01 --seg-audio --preview-dir out/preview
open out/preview/s01.mp4        # 打开给用户看

--seg-audio 的段音频只活在这条预览里(渲完即删);拼装 / 交付仍走 --audio 整条音轨,纪律 A 不破。 4. 问一次,等回答(AskUserQuestion 类工具,两个选项,不替用户决定):「样板确认,继续做其余镜头」/「先改样板」。 改完重渲同一条预览再问;样板未确认前不得动其余镜头。确认后样板镜的蒙皮 / 字幕 / 相机幅度就是全片基线,其余镜头不得另起一套。

布局红线(数值表 design-language.md §5;几何总纲 references/layout.md)

  • 字幕位置 / 宽度 / 字号 / 常驻件方位按画幅取 design-language §5 表(竖屏常驻件必须左下,右缘是抖音点赞栏)
  • 横屏内容主列 ≤1440px 居中、边距 action-safe 96 / 标题 160(design-language §3;栏跨度与吸附见 layout.md §1)
  • 通用:切镜后 ≤10 帧必须有主视觉入场;深色场景隐藏全局顶部标题; 文字不叠截图文字(加白底卡);卡片文字防裁切(预留 padding)
  • 人物在场:先跑 scripts/face_bbox.py 实测人脸安全区(口径 host-footage.md §3), 任何文字/卡片/字幕及其背景全时刻不得进入;主信息面板放人物对侧

⑤-2 工作台实时看板(骨架搭完就开,制作全程常开)

把 ⑧ 里"交付后才打开工作台"前移到这里:⑤-1 合成骨架搭完(shots.json + Main.tsx 落盘)就接入并打开工作台,用户此后随时能看到 "做到哪了、哪镜什么状态"、能播当前实时成片、能点单镜有声预览;agent 每存一次盘预览就刷新,不用等成片(workbench/docs/live-pipeline.md)。 打开即多轨(2026-09-21 用户定版:制作中的看板与交付面是同一个多轨工作台,不是单轨"进度台")——骨架一搭完,时间线上就是 字幕 / 转场标记 / 全部镜头(占位镜画斜纹)/ 幕底 / 配音 / 逐条音效各轨;agent 每落一条 cue、每实现一镜、每改一句字幕,对应轨上 ≤3s 出现 (shots / 场景 / sfx.ts / 字幕一落盘就按稳定 id 自动同步,用户改过的不覆盖);进度轨 + 每个镜头 clip 的角标显示 占位 / 已实现 / 已渲 / 已过闸。

bash <skill根>/runtime/check-runtime.sh                                # 依赖统一在 runtime/,这一步顺手把 workbench/node_modules 链好(不在 workbench 里 npm install)
cd <skill根>/workbench
bash scripts/link-project.sh <本片工程>       # kbsrc → remotion/src;public/ 先清掉指向别的工程的旧链接再逐项软链;末行必须打印「拆解契约 OK」——否则多轨进不去,它会说缺哪个文件
npm run dev &                                                          # 已在跑就跳过;链接变了要重跑一次 npm run gen;契约文件是后补的要重启 dev server(别名启动时定)
sleep 4 && curl -s http://localhost:5199 | grep -q '动效工作台' && echo "工作台 OK" || echo "FAIL: 工作台未起"
open 'http://localhost:5199/?tracks'                                   # 进来就是多轨(字幕 / 转场 / 逐镜 / 幕底 / 配音 / 音效 + 进度轨),之后自动跟盘;?live 同义
                                                                       # 契约不全不会装任何工程,右下角点名缺哪个模块——回 ⑤-1 补齐;单轨"成片(实时)"2026-09-21 已下线
  • 状态清单 pipeline.json(工程根):工作台 dev server 按盘上产物实时推导每镜状态(占位 / 已实现 / 已渲 / 已过闸、场景比段新 = 过期), 不依赖 agent 记得写;agent 只在盘上推不出的事上落一笔,都走 node <skill根>/scripts/pipeline_state.mjs(在工程根或 remotion/ 下执行):

    时机命令说明
    ⑥⑦ 某镜机器闸 + 审片过--pass s03,s04进度轨变绿;--pass all 整片
    审片发现未清缺陷--issue "s07|P1|字幕带压到人脸安全区 12.3–12.8s"进度块红点 + 镜头面板列出;修完 --clear-issues s07
    阶段与推断不符时--stage ⑥⑦平时不用,阶段按产物自动推
    任何时候想核对不带参数重算并落盘,末行打印摘要
  • 半成品不盖页:Vite 报错不再罩住整个工作台,右下角一条提示 + 画面停在上一版;单 clip 渲染出错只把那一格画红; 页面打开时工程就是坏的,修好后成片卡自动恢复(载入失败不缓存)。只有 Player 里容错——render_shots / 工作台导出走 Remotion CLI 时任何卡抛错就是渲染失败,不会把红色错误画面当成片。

  • 看板画布 = 工程原尺寸(Root.tsx 的 width / height / fps 必须写数字字面量,写变量会按默认 1920×1080@30 并在 npm run gen 时告警)。

  • --pass 绑定当时的产物:段被删 / 场景之后又改过 → 该镜回到推导状态并提示"曾通过",重渲复核后再 --pass。

  • Main 组件别调 getInputProps()(Remotion Player 里必抛,看板上那一格会红):debug / sfxSolo 之类开关改成组件 props(Composition defaultProps), 或守卫 typeof window !== 'undefined' && !(window as any).remotion_isPlayer。

  • 看板只看不驱动:不提供"点按钮触发某一步"的接口,skill 仍是主控。

  • 拆解契约(工作台多轨 + 逐镜调参吃这几个导出,template/motion-systems/ 都有样例): shots.ts 导出 SHOTS(每镜 lead / tail 帧数、hardOut)+ shotSequence;scenes/index.ts 导出 SCENES(镜头 id → 场景组件)与 SCENE_PARAMS(镜头 id → 该场景的 PARAMS); 每个场景 export const PARAMS = [...] as const satisfies readonly ParamField[],场景内 const p = useParams(shot.id, PARAMS) 取值——表里只放语境级参数 (文案 / 颜色 / 字号 / 位置 / 入场方向),词锚时刻、时长、缓动、几何比例、层级是命门不进表(design-language §0.4 同一条线); Subtitles.tsx 导出 Subtitles + phrases()(全部可见字幕段:已扣静音区、已做显示映射)+ SubtitleLine(单句静态渲染,Subtitles 自己也用它画); Environment.tsx 导出 Environment(幕底画布,画在所有镜头之下)与 Overlays(幕级覆盖:黑震切帧 / 落幕等,画在镜头之上、字幕之下),Main.tsx 从这里取; params.ts 照模板抄(useParams / ParamsProvider / OVERRIDES),remotion/overrides.json 建成 {}; 配音文件放 public/narration.wav(模板 MainVideo-example.tsx 的约定;工作台多轨的配音块按 narration / full 解析,别叫别的名字——2026-09-21 实测叫错名字多轨整条静音、导出丢人声); 实拍底床用 template/components/bed.tsx 的 Bed(根元素 className="wb-bed")——工作台右键导透明通道时按这个标记把底床去掉,只留动效本体。 overrides.json 归工作台写、agent 永不改:用户在面板改的键以它为准,agent 只改 tsx 默认值——这就是双写冲突的解法; 渲染(render_shots / 工作台导出)读同一份,所以定版前要看一眼它是否为空(用户调过参就以调过的为准交付,交付说明里写明)。 契约是否齐全由机器闸 python3 scripts/workbench_contract_lint.py <工程根> 核(⑥⑦ 六条闸之一;样板镜阶段加 --allow-placeholder)。

⑥⑦ 渲染 + 三重验收(机器闸全过 → 1 轮审片 → 交付)

迭代纪律(管着本节全部循环)

  • 闸报 FAIL 先读闸怎么量的,再动手改(闸源码就在 scripts/):motion_check 的静止判定是 freezedetect n=0.003 d=0.8 (逐帧平均像素差 >0.3% 才算动)——平滑渐变、漂背景、纯透明度呼吸都不产生像素变化,相机缩放才改每一个像素; sfx_check --mix 量的是 [t−0.05, t+0.45] 0.5s 窗。读闸还能判出闸本身够不够得着 (句间气口 <0.3s 而音效电平上限 −22dB 时,UNMASKED 在数学上不可达)——这种"输入决定、不是本片可修"的结论必须早下。
  • 静帧优先:render_stills.mjs 约 10s 一批,能答掉九成"这个改动对不对"(落点/遮挡/文案/配色/层级/取景); 整渲只留给跑机器闸和静帧查不了的时域缺陷(抖动/闪烁/音画/freezedetect)。
  • 改哪段渲哪段、复审改动攒批再渲:--only s2,s4 / --changed sNN 只渲改动段, 复核时逐段对时间戳确认"改的段是新的、没改的段沿用缓存",别习惯性 --all;多批 P0/P1 攒成 1~2 批再渲。

⑥-0 渲染前静态预检(零母版成本)——三道把返修拦在母版前:

python3 scripts/beat_gap_check.py remotion/beats.json remotion/shots.json   # 空台预检(advisory,从节拍表推算)
# 每条 WARN 都要答得出"这窗里什么在动":正常答案只有一个——该镜的相机极缓推拉覆盖了这窗(不补 idle/呼吸层);相机确在动就 --ok 声明
cd remotion && python3 ../scripts/freeze_probe.py --shots shots.json          # 静止探针:每镜 3 个时点渲「相隔 0.8s 的两帧」,按 freezedetect 同款 yuv420p 均差判
# 量的是真实合成像素(beat_gap_check 看不见持续运动);15 镜 90 张静帧实测 ~2 分钟,替掉"渲 10~20 分钟母版才知道 S06 过不了静止闸"。
# 2026-09-06 v4 实测:45 个采样点与母版 freezedetect 一致 98%(1 个 mafd 0.72 的边界点多报);是单点粗筛,不是全覆盖

清单二·状态切换窗:人物轨道每个 half↔chip 切换点、每个 wipe 时刻 ±0.5s 列入静帧抽样点—— 字幕带换位与人物几何过渡的穿越冲突(黑字压黑衣)只藏在这种窗口里,句级/锚点抽帧都错过。 字幕带换位必须等几何过渡完成再切(half→chip 延后 ~0.45s 落位)。

⑥-1 静帧抽样(一次 bundle 批量渲,比逐张 npx remotion still 快一个量级):

# 两个 node 渲染脚本都必须在工程 remotion/ 目录下执行(Remotion 模块从工程自己的 node_modules 解析,
# 并自动加载工程的 remotion.config.ts——webpack alias / publicDir / browserExecutable 与 CLI 渲染一致;
# 吃 inputProps 的合成给 --props @props.json;素材是符号链接时 --public-dir 指向解引用同步后的目录)。
# 首跑没装浏览器会联网下载 Chrome Headless Shell(~95MB);离线机先 npx remotion browser ensure,或 --browser 指向本机 headless shell
# 中间帧格式:renderMedia 不读 remotion.config.ts,此前永远是默认 JPEG-80——render_shots 现在透传配置里显式设的
# setVideoImageFormat / setJpegQuality / setCrf,命令行 --image-format png|jpeg --jpeg-quality 95 --crf 18 再覆盖,
# 生效值打在日志首行 `encode: …`。默认建议 jpegQuality 95:2026-09-06 白底片同段三格式实测,jpeg95 对 png 的 PSNR 47.9dB、
# jpeg80 46.0dB,静态窗噪声底三者相同(2.83/2.83/3.07),渲染时间差异小于本机运行间噪声——格式按画质定不按速度定;
# 深底渐变片的色带(用户实测 raw_mean 0.67→0.39)本次没有对应素材复测,深底风格档仍按 png。
node <skill根>/scripts/render_stills.mjs --times 2.0,7.2,...   # 抽样点=每镜入/出+关键锚点+状态切换窗

⑥-1.5 定渲染节奏(样板镜已在 ⑤-1 由用户确认,这里不再单独渲首镜给用户看;首渲仍禁止直接 --all——先问节奏): 若 ⑤-1 之后改过全局系统(theme / 字幕 / 相机 / 幕底),先 --only s01 --seg-audio --preview-dir out/preview 重出样板镜,自查与确认版一致即可,不必再问用户。 然后问一次(AskUserQuestion 类工具,两个选项,不替用户决定):

  1. 整片渲:⑥-2 的 --all --parallel 4 --concat … --audio … --mux …;
  2. 逐镜节奏:--only s02 --audio … --preview-dir out/preview 渲一镜、开给用户看一镜、等用户说"继续 / 改"再下一镜, 改动用 --changed sNN;全部看完再 --concat + --mux 拼装。 两种节奏最后都要过 ⑥-2 的帧数断言与 ⑦ 三重验收——"用户看过"不等于"验收过",机器闸与独立审片照做。

⑥-2 分段渲染母版制——按镜头切段、段内单进程连续渲(段内光栅自洽;多 tab 并发会产生周期性相位抖动), 段间 --parallel 4 实测比单进程快 1.3~1.8×(本机负载不同两次分别 253→139s、307→230s,4 镜 900 帧); 整条音轨没有光栅问题,--audio-concurrency 4(默认)实测 419s→175s(116s 片),imageFormat:'none' 只省 6%——浏览器逐帧 seek 才是音轨渲染的主成本; 段边界都是切镜点,K 段并行:

# 在工程 remotion/ 目录下执行。首渲:K 段并行 + 拼装 + 整条音轨 + 混音
node <skill根>/scripts/render_shots.mjs --shots shots.json --all --parallel 4 \
     --concat out/assembled.mp4 --audio out/full-mix.wav --mux out/vN.mp4
# 改一个镜头 → 只重渲该段±邻段(lead/tail 交叠波及邻镜边缘)再拼装
node <skill根>/scripts/render_shots.mjs --shots shots.json --changed s14 \
     --concat out/assembled.mp4 --audio out/full-mix.wav --mux out/vN+1.mp4
npx remotion render src/entry.ts <Comp> out/sfx-solo.wav --props='{"sfxSolo":true}' --codec=wav

音画对齐三条硬纪律(脚本内建断言,缺一必错位):音轨整条不分段(视频段全 muted, 音轨单渲一次交付时混入——每段各带 AAC 再拼会因编码器前导延迟逐段错位); 段边界取整与 Sequence 同规则(差 1 帧=画面节拍整体偏 33ms);帧数断言(每段实数帧+ 拼装总帧数精确相等,不等即 FAIL)。音轨缓存过三关才复用:时长 == 合成时长、素材/inputProps/时序配置文件 (beats.json、cues.json、src/sfx.ts 等文件名含 sfx|cue|beat|audio|sound|timing)三项指纹未变、非半截临时文件; 指纹看不见的改动(音量常量写在组件里)用 --force-audio。 修复验证同理只渲受影响段过闸(freezedetect 单段可跑),不整渲。

# —— 关卡 1 机器闸:六条命令一次跑完,全 PASS 才进关卡 2 独立审片 ——
python3 scripts/motion_check.py out/vN.mp4 --baseline remotion/public/dh/host.webm --window <t>,<人物区 W:H:X:Y>
                                                  # 画面健康:静止段 + 抖动。抖动先查重复帧签名(人物区周期性近零差 = 素材帧率病,
                                                  # 处方在 preflight,--concurrency=1 治不了),再查并发光栅;--baseline 同窗量源片,
                                                  # 素材自带的噪声降 WARN——有人物素材的片必给,人物区窗必加
python3 scripts/sfx_check.py out/sfx-solo.wav cues.json                  # 音效在场(峰值 ≥−45dBFS)
python3 scripts/sfx_check.py --mix out/vN.mp4 audio/full.wav cues.json --timestamps audio/timestamps.json
                                                  # 音效可听(掩蔽分级);--timestamps 数气口,UNMASKED 门槛不超过气口数并打印"不可达"原因
python3 scripts/card_lint.py remotion/src <slug,slug,...>                # 卡片保真(复制自 template/cards)
python3 scripts/beat_lint.py remotion/beats.json audio/timestamps.json --shots remotion/shots.json --anchors anchors.json
                                                  # 词落点 |Δ|≤0.1s + 镜尾保护带 ≥0.5s + label 只许 [A-Za-z0-9_-](进文件名/JS 字符串)
python3 scripts/workbench_contract_lint.py <本片工程根>                      # 工作台拆解契约(⑤-2):六个契约文件 · SCENES/SCENE_PARAMS 与 shots.json 对账 ·
                                                  # 每镜 PARAMS + useParams · params.ts / overrides.json · Subtitles 的 phrases/SubtitleLine——
                                                  # 漏一个导出 = 用户打开工作台才发现按钮灰 / 面板空;⑤-1 只有样板镜时加 --allow-placeholder
# 评审材料抽帧:每句 2 帧 + 动效锚点帧(anchors.json 从 beats.json 导出)
# 连拍三帧对只抽 anchors.json 里标了 "burst": true 的锚点——状态切换(两态翻转/换场/砸入落位)
# 与高风险区域必须标;其余锚点只抽定妆帧。
# motion_check 的抖动闸只量 ≤12 个 18s 间隔的固定裁剪窗、快速运动窗还跳过——窗外的短闪烁它看不见,
# 所以连拍不是可选项;--bursts 全抽只在抖动闸报警需人眼定位时用。同一份 anchors.json 也喂给 motion_check
python3 scripts/qa_extract.py out/vN.mp4 audio/timestamps.json /tmp/qa_vN 540 anchors.json
python3 scripts/motion_check.py out/vN.mp4 --anchors anchors.json   # 锚点 t+0.6s 各加一窗,结尾打印实际覆盖窗数
# 评审拼图:帧目录拼 3×4 网格(评审先整版浏览、可疑帧再回原目录单张放大)
python3 scripts/contact_sheet.py /tmp/qa_vN /tmp/qa_vN_sheets

机器闸口径备忘:音效两查要求工程主音轨支持 {!getInputProps().sfxSolo && <Audio .../>}; 可听度 MASKED>50% 或 UNMASKED 少于 max(3, 片长/30s) 即 FAIL("81/81 在场但全被人声掩蔽"是典型翻车), 良品口径:转场/边界 cue 落句间 ~0.3s 气口出声;shots.json = 分镜表导出的 [{"id","start","end"}](与 shots.ts 同源)。

关卡 2 独立审片(协议正主 references/review-protocol.md,评审 subagent 被派时必须先读它): 必须派全新上下文的 subagent——不许制作者自评、禁止 fork/复用制作对话当"评审"、禁止对同一评审做 followup 复审 (fork 出来的评审继承制作者视角,对照物又是制作者自己写的 SHOTBOOK,形成自证闭环)。 派发 / 等待 / 判活 / 重派按 review-protocol §1.6 的 harness 无关原语表(PACKET / DISPATCH / FAN-OUT / WAIT / LIVENESS / RE-DISPATCH,Claude Code · Codex · headless 各一列);WAIT 以落盘 REVIEW.md 的结束行为准,不以子代理完成通知为准。 制作者自己的首轮版式过目也委托子代理(只回文字缺陷清单,几十张图的图像 token 不进主上下文)。 备齐协议 §1.2 的材料五件套,评审按 rubric 出 P0/P1/P2 清单,修完 P0 + P1 才算过关;返修按协议 §3 给量测数字、只渲受影响段。 关卡 3 规则合规:cinematography.md §5 八条逐镜核 + 交付前终检(调试 overlay 关、成片缩到 390px 宽可读),条目见 review-protocol.md §2。 审片循环:机器闸全过后只做 1 轮独立审片 → 修 P0/P1 → 即交付,同时问用户是否续审(自动轮次封顶 3 轮) 并打开动效工作台(⑧);遗留 P2 清单随交付物。细则 review-protocol.md §4。

⑧ 交付

两遍 loudnorm(单遍是动态模式,会压音效瞬态;且 loudnorm 内部升到 192kHz,不加 -ar 会把 96k 漏进 AAC——2026-09-06 实测):

# 第一遍量测(只看 stderr 的 JSON)
ffmpeg -i out/final.mp4 -af "loudnorm=I=-15:TP=-1.5:LRA=11:print_format=json" -f null - 2>&1 | sed -n '/^{/,/^}/p' > /tmp/ln.json
# 第二遍线性归一(measured_* 从 /tmp/ln.json 抄:input_i / input_tp / input_lra / input_thresh / target_offset)
ffmpeg -i out/final.mp4 -c:v copy \
  -af "loudnorm=I=-15:TP=-1.5:LRA=11:measured_I=<input_i>:measured_TP=<input_tp>:measured_LRA=<input_lra>:measured_thresh=<input_thresh>:offset=<target_offset>:linear=true" \
  -ar 48000 -c:a aac -b:a 192k delivery.mp4

听一遍确认配音无爆音/截断、音效不压人声不叠帧(loudnorm 之后音效相对电平会变)—— agent 自己听不了成品,sfx_check.py --mix 就是耳听的机器替身:交付前必须对 delivery.mp4 重跑一次; 简介附素材来源行(用了库内采样时加 sfx 来源,见 demos/_lib/sfx/ATTRIBUTION.md)。

交付时工作台应已自 ⑤-2 起常开(没开就按 ⑤-2 那段接入并打开;不要等用户问;与"是否继续自动审改"的询问同时给出, 见 ⑥⑦ 审片循环制度)——给用户一个剪映式界面做人工微调,并 pipeline_state.mjs --pass … 把过闸镜头钉绿:

bash <skill根>/runtime/check-runtime.sh          # 统一依赖体检 + 链好 workbench/node_modules(不在 workbench 里 npm install)
cd <skill根>/workbench
bash scripts/link-project.sh <本片工程>          # 链接本片工程(机器本地符号链接,不进库;手写 ln -sfn 循环不会替换指向旧工程目录的链接——2026-09-15 实测 logos 仍指上一支片)
mkdir -p public && for f in <本片工程>/remotion/public/*; do ln -sfn "$f" "public/$(basename "$f")"; done
npm run dev &                                     # 浏览器打开 http://localhost:5199/?tracks 并告知用户(多轨面;?live 同义)
sleep 4 && curl -s http://localhost:5199 | grep -q '动效工作台' && echo "工作台 OK" || echo "FAIL: 工作台未起——禁止用 remotion studio 代替"

防误操作:交付给用户的界面只能是这个工作台(页面标题「TalkCraft Workbench · 动效工作台」,上面那行断言就是核验)。 npx remotion studio(工程内)或工作台的 npm run studio 是开发者调参入口,不是交付面,不得用它代替工作台; npm run dev 必须从 <skill根>/workbench 执行(别在本片工程目录里起)。

工作台打开(?tracks)就是多轨:逐句字幕(文本可改)/ 幕级覆盖 / 转场标记 / 逐镜参数化镜头 / 幕底 / 配音 / 逐条音效——自 ⑤-2 起它就在,交付时只是全部变绿; 交付面必须是这个多轨面,不是单轨「成片(实时)」(2026-09-21 用户反馈:成片做完打开的还是单轨进度台,没法分轨改背景 / 动效 / 字幕 / 音效); 镜头里每个场景 PARAMS 声明的文案 / 颜色 / 字号 / 位置 / 入场方向逐项可调(词锚节拍、时长、缓动、相机固定), 改动写回本片 remotion/overrides.json,渲染读同一份;改完点「导出成片」(内置 Remotion 渲染,遵守单并发纪律)。详见 workbench/README.md / GUIDE.md ⑥。 接入按真实路径解析、契约模块缺哪个只降级哪个(workbench/kbsrc.map.mjs);本 skill 产出的工程按 ⑤「拆解契约」六个文件写就能拆—— 拆解按钮灰着,先看 npm run gen 末行报的是缺哪个契约文件,别去补造 promo 形态的 PromoScenes / Host。 发布时**推荐(非强制)**在简介 @ 一下本 skill 作者——对作者是最好的支持: X @VincentWei93 · 抖音 @Vincent · 小红书 @Vincent。 有建议、反馈欢迎扫 README「微信讨论群」小节的二维码进交流群。

目录路由

要做什么看哪里
定视觉语言(色板/字阶/间距/字幕规范)· 幕底 12 款references/design-language.md(Apple 范式默认版;§1.1 幕底菜单 → template/motion-systems/backdrop.tsx)
排版:放哪 / 多大 / 怎么对齐(栅格 · 间距令牌 · 居中 · 字阶 · 碰撞 · 校验九项)references/layout.md
给镜头做背景/主体/文字分层设计references/shot-design.md(三面工作单 + 七型预设)
镜头方法论/反PPT/SHOTBOOK格式/验收references/cinematography.md(+ shotbook-example.md)
审片:关卡 2 材料五件套 / rubric / 缺陷分级 · 关卡 3 · 返修纪律 · 审片循环references/review-protocol.md(评审 subagent 必读)
转场(六式代码)/ 长镜头template/motion-systems/transitions.tsx / longtake.tsx(cinematography.md §3、§3.5)
纯文字镜配线稿示意图(G5:词汇 · 语义图形词典 · 节拍纪律 · 落位自检)references/schematic.md → template/motion-systems/schematic.tsx + icons.ts(scripts/fetch_icons.py 抓 Iconify lucide)
视频容器边框八式(单视频镜不裸贴、不装假播放器;任何卡的视频区可包)template/components/theme-frame.tsx(规则与选式:design-language §1.3)
选动效/查参数和坑references/taxonomy.md(两道生成索引:输入类型 / 语义)→ references/cards/ → template/cards/(tsx 源码)+ demos//gallery/(预览)
口播稿逐句语义标注(②-1)· 选卡候选表 · 卡索引生成references/semantic-annotation.md · scripts/semantic_annotate.py · scripts/card_match.py · scripts/cards_index.py
找素材 · 配图采集 · 网页拍摄素材采集(全页 2× 长图 + DOM 坐标 JSON)references/broll-sources.md
开工体检(③ 素材期 --media-only / ④→⑤ 闸全量:人物素材帧率·重复帧·时长·比例 + SHOTBOOK 素材对账·未完成清单)scripts/preflight.py
静止探针(母版前用真实合成帧差预判 freezedetect)scripts/freeze_probe.py
人物素材(输入规格 / CPU 抠像 / 人脸安全区)· 与 B-roll 同屏怎么摆references/host-footage.md + scripts/face_bbox.py
新增配方卡references/demo-spec.md,验证 node scripts/verify-demo.mjs <slug>
可复制代码template/cards/(108 卡逐卡自包含 tsx)、template/motion-systems/(极缓推拉相机/让位/桥)、template/components/(字幕/花字/铅笔/吉祥物)
成片后人工微调 / 导出workbench/(剪映式工作台:多轨时间线 + 全卡参数化 + 成片拆解 + Remotion 渲染导出)
制作全程实时看板(⑤-2 起常开、打开即多轨且自动跟盘:进度轨 / 镜头状态角标 / 阶段栏 / 单镜预览 / 半成品不盖页)· 状态清单workbench/docs/live-pipeline.md · scripts/pipeline_state.mjs(--pass / --issue / --stage;状态按产物自动推)
字级时间戳(本机 CPU)scripts/timestamps_cpu.py(FireRedASR2-CTC 默认 / faster-whisper 备选,+ 口播稿逐字对齐)→ scripts/make_timing.py
一键配音+时间戳(Fish Audio 免费层)scripts/tts_fishaudio.py(基于 s2.1-pro-free 流式 TTS,生成 full.wav + timestamps.json + 可选 timing.json)
配音预剪(口水词 / 结巴重说 / 过长停顿,时间戳之前跑;同一 EDL 剪人物视频)scripts/voice_trim.py(②-0;稿子为真值只剪稿外插入段;词表来源 ASR / 逐字 SRT / 词级 JSON;cuts.json EDL 含时间轴映射)
闸报 FAIL 了怎么办 · 怎么少烧母版⑥⑦「迭代纪律」三条——先读闸怎么量的再改 · 静帧优先 · 改哪段渲哪段、复审改动攒批
机器闸(画面健康 / 保真 / 词落点+镜尾 / 音效)scripts/motion_check.py(静止段+并发光栅抖动双判定)/ scripts/card_lint.py(卡片须复制自 template/cards)/ scripts/beat_lint.py(词落点对 timestamps + --shots 镜尾保护带)/ scripts/sfx_check.py(solo 在场 + --mix 可听度)
渲染提速(分段母版 / 批量静帧 / 空台预检 / 评审拼图)· 首镜先做先确认(⑤-1)scripts/render_shots.mjs(段渲+拼装+音轨混入+帧数断言;--changed sNN 单镜头迭代 53s;--only s01 --seg-audio --preview-dir 样板镜有声预览、不渲整条音轨(⑤-1);⑥-1.5 问用户整片还是逐镜)/ scripts/render_stills.mjs(一次 bundle 批量 still)/ scripts/beat_gap_check.py(渲染前空台预检)/ scripts/contact_sheet.py(QA 帧拼 3×4 网格)
动效配套音效逐卡 cue 表 demos/_lib/sfx-map.js(口味纪律见 references/demo-spec.md「Demo 硬性要求」第 8 条);制作端 node scripts/sfx_dump.mjs 导出采样

Similar Skills

brand-guidelines
anthropics/skills180k

brand-guidelines

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

AI & agents

internal-comms
anthropics/skills180k

internal-comms

A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).

AI & agents

template-skill
anthropics/skills180k

template-skill

Replace with description of the skill and when Claude should use it.

AI & agents

mcp-builder
anthropics/skills180k

mcp-builder

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

AI & agents

algorithmic-art
anthropics/skills180k

algorithmic-art

Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.

AI & agents

academy-guide
anthropics/skills180k

academy-guide

Stop and check this skill before finishing any reply to a question about how to use Claude or a Claude product — it recommends matching courses, tutorials, and use cases from Claude Academy (academy.claude.com), Anthropic's learning hub. Trigger on: "how do I", "how can I", "getting started with", "what can Claude do", "teach me", "learn to use"; questions about artifacts, projects, skills, plugins, connectors, MCP; requests about rolling Claude out to a team, class, or organization; and any ask for training materials, onboarding content, or learning resources. Use it when the user is learning how to use a feature or product — not when they are mid-task and just want the task done. This skill composes with other skills: after consulting product documentation to answer how a Claude feature works, also check here for a matching course or tutorial — a docs-grounded answer and an Academy recommendation belong together. Only recommend on a strong match; never invent Academy content.

AI & agents