Summary
用 Remotion 制作「纸片分层动画」视频:把背景、主角、配角、前景分别做成独立 PNG 素材,再让每一层按不同节奏运动,靠前后遮挡制造纵深。图片素材用 apiz CLI(nano-banana-pro)生成 + 绿幕抠图,配音用 MiniMax(apiz speak / 直连…
liangdabiao/video-skills-toolkit · Archived
用 Remotion 制作「纸片分层动画」视频:把背景、主角、?
npx skills add liangdabiao/video-skills-toolkit --skill paper-cutout-remotion
用 Remotion 制作「纸片分层动画」视频:把背景、主角、配角、前景分别做成独立 PNG 素材,再让每一层按不同节奏运动,靠前后遮挡制造纵深。图片素材用 apiz CLI(nano-banana-pro)生成 + 绿幕抠图,配音用 MiniMax(apiz speak / 直连…
This repository is archived — consider an actively maintained alternative.
Convert local audio/video files or public media URLs into subtitle files by uploading local fil…
3 installs用 Remotion 制作可复用的口播视频工程:支持口播音频/视频、右下角圆形 PIP、底部同步字幕、顶部章节…
3 installs用 Remotion 制作「小白学AI」系列的手绘?
3 installs用 Remotion 制作数学证明/几何动画视频:深底高饱和 + 精准 SVG 几何 + ?
3 installsRelated neighbors and high-traction skills in the same topics — useful to compare before installing.
Router for all Remotion skills
515.3K installsExport a Remotion video
74.7K installsCreate a new Remotion video
74.5K installsTranscribing, displaying and animating captions
72.5K installsContent, animation and effects best practices
70.1K installsStructure Remotion markup for interactivity
68.4K installsOther skills from liangdabiao/video-skills-toolkit.
npx skills add liangdabiao/video-skills-toolkit
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
main
Files included with this skill beyond the listing page.
SKILL.md
14,674 B
README.md
12,269 B
SUMMARY.md
653 B
把一份分镜脚本变成纸片分层风格的 Remotion 视频。核心方法论:不是生成一张漂亮图加镜头移动,而是把画面拆成背景/后排/主体/前景四层独立素材,让每层按不同节奏运动,靠前后遮挡制造纵深立体感。
这套方法不只适合历史题材。只要画面能拆成"背景、主角、配角、前景"——历史人物、知识科普、商业故事、人物关系、城市发展——都能用同样的流程制作。
工具链:apiz CLI(图片生成)+ Python/Pillow/NumPy(绿幕抠图拆层)+ MiniMax(apiz speak 配音,直连 API fallback)+ Remotion(React 控制图层/动画/字幕/渲染)+ FFmpeg(验收)。
配套参考:
references/components.mdreferences/layering.md(纸片风的灵魂,必读)references/prompt-recipes.md按以下顺序执行,每步完成再做下一步。顺序乱了会导致素材比例错误、抠图失败、主次不清。
先定镜头,不要先画图。同一个人物在全景和特写里的大小、位置、朝向都不同,先随便生成素材,后面必然返工。
每个镜头先回答:谁最大?配角在哪?地平线在哪?
见 references/layering.md。每个镜头至少拆成:
mkdir "<VIDEO_WORKSPACE>/<项目名>"
cp -R "./skills/paper-cutout-remotion/templates/remotion-project/" \
"<VIDEO_WORKSPACE>/<项目名>/"
cd "<VIDEO_WORKSPACE>/<项目名>" && npm install
⚠️ 用原生 npm install,不要 rtk npm install(rtk 会翻译成 npm run install 报错)。
在项目根建素材目录:
mkdir -p public/assets/plates public/assets/layers public/assets/source
mkdir -p public/audio/narration public/audio/sfx
背景底板只保留环境(山水/宫殿/纸纹/撕纸边缘/装饰)。绝对不要把主要人物画进背景——画进去就没法独立飞入、摇摆、调整大小了。
# 单张
python scripts/gen_plates.py "唐代长安宫殿全景,水墨远山,宣纸纹理,撕纸边缘" \
public/assets/plates/01-tang-wide-bg.png
# 批量(plates_spec.yaml)
python scripts/gen_plates.py --batch plates_spec.yaml public/assets/plates/
脚本会自动追加"无人物"约束。提示词配方见 references/prompt-recipes.md。
角色用纯绿背景生成(方便后续 chroma key 抠图)。提示词必须强制:朝向、完整全身、白色剪纸描边、纯绿背景、无文字水印。脚本会自动追加这些约束。
# 先写 assets_spec.yaml(角色清单,见 scripts/gen_characters.py 注释)
# dry-run 检查提示词
python scripts/gen_characters.py assets_spec.yaml public/assets/source/ --dry-run
# 实际生成
python scripts/gen_characters.py assets_spec.yaml public/assets/source/
把带绿背景的素材表抠成透明 PNG,多人素材表按网格拆成独立文件。
# 单人物(只抠图不拆)
python scripts/split_sheet_green.py public/assets/source/emperor.png \
public/assets/layers emperor 1
# 6 人群臣素材表(自动推算网格)
python scripts/split_sheet_green.py public/assets/source/ministers.png \
public/assets/layers minister 6
# 显式 3 列 2 行
python scripts/split_sheet_green.py public/assets/source/ministers.png \
public/assets/layers minister 6 --cols 3 --rows 2
抠完后检查 *-full-alpha.png(完整抠图结果)确认绿幕干净、边缘没有绿残留。若有绿残留,调大 splitsheetgreen.py 的 EDGE_FEATHER,或提示词强化 "pure flat solid green, no gradient"。
不要一拿到素材就加动画。先在 scenes.tsx 里把所有人物静止摆好,检查:
只改 src/scenes.tsx(场景组件)和 src/Root.tsx(SCENES 表)。不要改 theme.ts / ui.tsx / cutout.tsx(风格锁定文件)。
按四层模型分配 zIndex(背景 0 / 后排 1-2 / 主体 3-4 / 前景 5-6 / 文字 10+),给每个 PaperActor 设 role 和 delay:
// 主角先出(delay 4),配角补充(delay 16-22),后排填充(delay 30-40)
<PaperActor src="assets/layers/emperor.png" x={960} y={920} width={650}
role="primary" delay={4} zIndex={3} seed="s2emp" />
<PaperActor src="assets/layers/maid-left.png" x={620} y={900} width={240}
role="secondary" delay={18} zIndex={5} seed="s2maid1" />
<PaperActor src="assets/layers/minister.png" x={1500} y={860} width={165}
role="tertiary" delay={34} zIndex={1} seed="s2min1" />
背景套 <BackgroundPan> 做 1-3% 慢速推镜。详细层级规范见 references/layering.md。
画面完成后,按场景生成旁白,用真实时长切镜头。
# 写 narration.yaml(见 scripts/gen_tts.py 注释)
python scripts/gen_tts.py narration.yaml --out-dir public/audio/narration
产出 s01.mp3 s02.mp3 ... + timeline.json(含 frames_playback)。
api.minimaxi.com/v1/t2a_v2(从 .env 读 minimaxi=KEY)用 timeline.json 的 frames_playback 回写 Root.tsx 的 SCENES 表 frames,并在每场 Sequence 里挂 <Audio src={staticFile('audio/narration/sNN.mp3')} />。
音效分层(按需求原文):
<Audio src={staticFile('audio/bgm.wav')} loop volume={0.3} />)sfx/impact.wav,次要 sfx/whoosh.wav,后排 sfx/tick.wavnpm run dev # Remotion Studio 逐帧预览
npx tsc --noEmit # 类型检查(长渲染前必做)
# 抽帧检查排版(每场接近结尾的静帧)
npx remotion still Episode --frame=<场景末帧-30> out/check-N.png
npm run render # 渲染 MP4
ffprobe -v error -show_streams -show_format out/episode.mp4 # 验收
| 项 | 值 |
|---|---|
| 画布 | 1920×1080 @ 30fps,宣纸米白底 #f3ead6 |
| 四层模型 | 背景(z0) → 后排(z1-2) → 主体(z3-4) → 前景(z5-6) → 文字(z10+) |
| roleMotion 三档 | primary(78/55/0.86) / secondary(58/38/0.90) / tertiary(38/22/0.95) |
| 白边+投影 | drop-shadow(4向 #f5eedc) + drop-shadow(0 18px 9px rgba(20,15,12,.32))(PAPER_FILTER,四项缺一不可) |
| 墨色 | #1f1a14(暖墨黑,标题/描边) |
| 强调色 | 朱砂红 #b8322a / 蓝 #2f5d8a / 橙 #c8732a / 绿 #3f7a3a / 金 #b8893a |
| 字体 | 标题/正文宋体栈 Source Han Serif SC;字幕黑体栈(小字可读性) |
| 素材 | 真实 PNG(apiz 生成 + 绿幕抠图),不是纯代码绘制 |
| 图片生成 | apiz CLI,默认 fal-ai/nano-banana-pro(最适合纸片/插画风) |
| 配音 | MiniMax,apiz speak(speech-2.8-hd)/ 直连 fallback(speech-02-hd),默认 female-shaonv |
public/
├── assets/
│ ├── plates/ # 背景底板(无人物,gen_plates 生成)
│ │ ├── 01-tang-wide-bg.png
│ │ └── 02-tang-close-bg.png
│ ├── source/ # 原始绿背景素材表(gen_characters 生成,抠图前)
│ │ └── ministers.png
│ └── layers/ # 抠好的透明角色 PNG(split_sheet 产出,scenes.tsx 引用这里)
│ ├── emperor-1.png
│ └── minister-1.png ...
├── audio/
│ ├── narration/ # 旁白 mp3 + timeline.json(gen_tts 产出)
│ ├── sfx/ # 入场音效 impact/whoosh/tick.wav
│ └── bgm.wav # 背景音乐
└── captions/ # (可选)SRT 字幕
*-full-alpha.png)npm install。EDGE_FEATHER。Error: 非 JSON,returncode≠0 时 libapiz.run_apiz 直接抛 stderr。speech-2.8-hd,直连 minimaxi API 用 speech-02-hd。两个脚本已分别用对的名字。apiz generate --json 的图片 URL 路径首次需校准:libapiz.extractimageurl() 多路径兜底,首次失败时看 .lastgenerate.json 把实际字段加到兜底列表最前。详见 references/prompt-recipes.md 末尾。s2emp、s2maid1)。references/layering.md。width × (图片高/宽比)。竖长条人物(高/宽常 2.3~2.6)很容易头顶超出 1080 画布。设坐标前先算:width × 高宽比 ≤ y - 60(留 60px 头顶余量)。例如高/宽=2.4、y=1030,则 width ≤ (1030-60)/2.4 ≈ 404。不确定时用 Python 量真实尺寸:Image.open(path).getbbox()。splitsheetgreen.py 对 count=1 输出 <prefix>-1.png(带 -1 后缀)。scenes.tsx 引用时要么用 -1 后缀,要么抠完后重命名去掉。多人素材表则天然是 <prefix>-1.png ~ <prefix>-N.png。remotion.config.ts 已配置自动检测本机 Chrome(C:/Program Files/Google/Chrome/Application/chrome.exe),跳过下载。换机器若 Chrome 路径不同,改这个配置。Config.setConcurrency(2) 规避。⚠️ 绝对不要同时跑多个 remotion render(前台+后台并发会触发此问题)。一次只跑一个渲染任务。参考成功案例 demo-wx-article-3(同款配置,带音频渲染正常)。<Audio> 组件要显式传 volume={1}。timeline.json 有两个字段:- framessource = ceil(音频秒×30)+15:原速音频实际需要的帧数(含 0.5s 收尾缓冲) - framesplayback = ceil(framessource/1.2):1.2x 加速后的压缩帧数 关键:如果音频是原速播放(没加 playbackRate={1.2}),SCENES 表的 frames 必须用 framessource,不能用 framesplayback。否则每段场景比音频短 1~2 秒,旁白没说完就被 FadeScene 淡出切场。只有当音频挂了 <Audio ... playbackRate={1.2} /> 时才用 framesplayback。古诗词等需要慢速韵味的场景建议原速。
apiz generate --json 成功后图片 URL 在 result.images[0].url,libapiz.extractimage_url() 已命中此路径,无需再手动校准。图片是公网 CDN(cdn-hk.51sux.com),urllib 直接下载即可。这套方法只要画面能拆成"背景、主角、配角、前景"就适用:
真正让纸片动画有层次的,不是多生成几张图,而是让每张图都承担明确的叙事位置。