liangdabiao/video-skills-toolkit · Archived

paper-cutout-remotion

用 Remotion 制作「纸片分层动画」视频:把背景、主角、?

First seen Jul 30, 2026

Installation

$ npx skills add liangdabiao/video-skills-toolkit --skill paper-cutout-remotion

Summary

用 Remotion 制作「纸片分层动画」视频:把背景、主角、配角、前景分别做成独立 PNG 素材,再让每一层按不同节奏运动,靠前后遮挡制造纵深。图片素材用 apiz CLI(nano-banana-pro)生成 + 绿幕抠图,配音用 MiniMax(apiz speak / 直连…

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from liangdabiao/video-skills-toolkit.

npx skills add liangdabiao/video-skills-toolkit

Browse all from liangdabiao/video-skills-toolkit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 173
License LICENSE
Default branch main
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 14,674 B
  • docs README.md 12,269 B
  • docs SUMMARY.md 653 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 4 installs

SKILL.md

Paper Cutout Remotion(纸片风分层动画)

把一份分镜脚本变成纸片分层风格的 Remotion 视频。核心方法论:不是生成一张漂亮图加镜头移动,而是把画面拆成背景/后排/主体/前景四层独立素材,让每层按不同节奏运动,靠前后遮挡制造纵深立体感。

这套方法不只适合历史题材。只要画面能拆成"背景、主角、配角、前景"——历史人物、知识科普、商业故事、人物关系、城市发展——都能用同样的流程制作。

工具链:apiz CLI(图片生成)+ Python/Pillow/NumPy(绿幕抠图拆层)+ MiniMax(apiz speak 配音,直连 API fallback)+ Remotion(React 控制图层/动画/字幕/渲染)+ FFmpeg(验收)。

配套参考

  • 组件 API 速查:references/components.md
  • 四层拆分方法论:references/layering.md(纸片风的灵魂,必读)
  • apiz 提示词配方:references/prompt-recipes.md

新项目工作流(10 步)

按以下顺序执行,每步完成再做下一步。顺序乱了会导致素材比例错误、抠图失败、主次不清。

1. 确定镜头(不要直接画图)

先定镜头,不要先画图。同一个人物在全景和特写里的大小、位置、朝向都不同,先随便生成素材,后面必然返工。

每个镜头先回答:谁最大?配角在哪?地平线在哪?

  • 全景镜头:交代规模(如"盛唐长安",皇帝最大居中,群臣最小)
  • 特写镜头:表现情绪/动作(如"万邦来朝",中央人物最大,前排跪拜次之)

2. 把每个镜头拆成四层

references/layering.md。每个镜头至少拆成:

  • 背景层(山水/宫殿/纸纹,无人物)
  • 后排层(远处群臣/侍从,tertiary)
  • 主体层(主角,primary,最大)
  • 前景层(近处人物/装饰,secondary,遮挡制造纵深)

3. 脚手架

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

4. 生成无人物背景底板(gen_plates.py)

背景底板只保留环境(山水/宫殿/纸纹/撕纸边缘/装饰)。绝对不要把主要人物画进背景——画进去就没法独立飞入、摇摆、调整大小了。

# 单张
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

5. 生成角色素材表(gen_characters.py)

角色用纯绿背景生成(方便后续 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/

6. 绿幕抠图 + 拆独立 PNG(splitsheetgreen.py)

把带绿背景的素材表抠成透明 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.pyEDGE_FEATHER,或提示词强化 "pure flat solid green, no gradient"。

7. 静态排版(先排版,再加动画)

不要一拿到素材就加动画。先在 scenes.tsx 里把所有人物静止摆好,检查:

  • 主角是不是最大、最醒目?
  • 配角有没有挡住主角的脸、手、关键道具?
  • 所有人物脚底是不是落在同一个合理地面上?
  • 朝向是否符合场景关系?

只改 src/scenes.tsx(场景组件)和 src/Root.tsx(SCENES 表)。不要改 theme.ts / ui.tsx / cutout.tsx(风格锁定文件)。

8. 设 zIndex 遮挡 + roleMotion 错峰动画

按四层模型分配 zIndex(背景 0 / 后排 1-2 / 主体 3-4 / 前景 5-6 / 文字 10+),给每个 PaperActorroledelay

// 主角先出(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

9. 配音 + 字幕 + 音效(gen_tts.py)

画面完成后,按场景生成旁白,用真实时长切镜头。

# 写 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)。

  • 优先 apiz speak(统一鉴权,内置下载)
  • 失败 fallback 直连 api.minimaxi.com/v1/t2a_v2(从 .envminimaxi=KEY

用 timeline.json 的 frames_playback 回写 Root.tsx 的 SCENES 表 frames,并在每场 Sequence 里挂 <Audio src={staticFile('audio/narration/sNN.mp3')} />

音效分层(按需求原文):

  • 旁白:每段一个 mp3,直接决定镜头时长
  • BGM:循环播放,音量在人声下方(<Audio src={staticFile('audio/bgm.wav')} loop volume={0.3} />
  • 入场音效:主角 sfx/impact.wav,次要 sfx/whoosh.wav,后排 sfx/tick.wav

10. 预览 + 验收 + 渲染

npm 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   # 验收

风格 DNA(不可变)

画布 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 字幕

验收清单(渲染前必过)

  • 主次分明:主角最大(约为后排 4 倍宽),配角不平均分布
  • 无遮挡穿帮:配角没挡住主角的脸/手/关键道具;朝向符合场景关系
  • 脚底同地面:所有人物 y 坐标落在同一合理地平线
  • 错峰入场:角色按 primary→secondary→tertiary 顺序出场,不同时出现
  • 白边+投影:每个 PaperActor 都带 PAPER_FILTER(剪纸感 + 立体感)
  • 音画同步:音效和人物入场帧对齐;字幕跟随旁白逐句
  • 字幕单层:底部一层,不重复,不挡人物脚部
  • FFmpeg 抽帧:每场渲接近结尾的静帧,检查上述各项
  • 绿幕干净:抠图后边缘无绿残留(检查 *-full-alpha.png

常见坑

  • rtk npm install 会失败,用原生 npm install
  • 先画图后定镜头必返工——人物比例/朝向/主次全错。务必先定镜头再生成素材。
  • 人物画进背景就废了——背景底板必须无人物,否则没法独立飞入。
  • 绿幕不纯(有渐变/阴影)→ 抠图绿残留。提示词强化 "pure flat solid green, no gradient, no shadow on background",或调大 EDGE_FEATHER
  • apiz 错误是单行 Error: 非 JSON,returncode≠0 时 libapiz.run_apiz 直接抛 stderr。
  • model 名不一致:apiz speak 用 speech-2.8-hd,直连 minimaxi API 用 speech-02-hd。两个脚本已分别用对的名字。
  • apiz 余额不足(实测可能很低)→ gentts 自动 fallback 直连;genplates/gen_characters 失败需充值,或换其他绘图模型。
  • apiz generate --json 的图片 URL 路径首次需校准libapiz.extractimageurl() 多路径兜底,首次失败时看 .lastgenerate.json 把实际字段加到兜底列表最前。详见 references/prompt-recipes.md 末尾。
  • seed 重复会让漂浮同步——每个 PaperActor 的 seed 带场景前缀+编号(s2emps2maid1)。
  • 前景 zIndex 必须大于主体——前景遮挡主体才制造纵深,不是反之。见 references/layering.md
  • 人物头顶出画(最易犯的排版错):PaperActor 的 y 是脚底,人物显示高度 = 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
  • Chrome Headless Shell 下载慢/失败(国内访问 storage.googleapis.com 不稳定,113MB 易超时):模板的 remotion.config.ts 已配置自动检测本机 Chrome(C:/Program Files/Google/Chrome/Application/chrome.exe),跳过下载。换机器若 Chrome 路径不同,改这个配置。
  • 音频混合失败(audio-mixing 目录缺失):根因是并发渲染竞争 Windows temp 目录。模板已设 Config.setConcurrency(2) 规避。⚠️ 绝对不要同时跑多个 remotion render(前台+后台并发会触发此问题)。一次只跑一个渲染任务。参考成功案例 demo-wx-article-3(同款配置,带音频渲染正常)。<Audio> 组件要显式传 volume={1}
  • 不要停留在无配音估时版——真实 TTS 生成后必须用 timeline.json 回写一版 frames。
  • 旁白被截断(没说完就切场):根因是帧数字段用错。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 URL 已校准(实测)apiz generate --json 成功后图片 URL 在 result.images[0].urllibapiz.extractimage_url() 已命中此路径,无需再手动校准。图片是公网 CDN(cdn-hk.51sux.com),urllib 直接下载即可。

适用范围

这套方法只要画面能拆成"背景、主角、配角、前景"就适用:

  • 历史人物 / 朝代叙事(唐/宋/明…)
  • 知识科普(人物 + 概念图解)
  • 商业故事(创始人/产品/用户分层)
  • 人物关系(家谱/组织/社交网络)
  • 城市发展(地标 + 人物 + 场景)

真正让纸片动画有层次的,不是多生成几张图,而是让每张图都承担明确的叙事位置。