@optima-chat/optima-agent 0.8.90 → 0.8.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/browser/SKILL.md +8 -0
- package/.claude/skills/homepage/SKILL.md +4 -3
- package/.claude/skills/kol-outreach/SKILL.md +360 -0
- package/.claude/skills/kol-outreach/template/campaign/CONFIG.md +60 -0
- package/.claude/skills/kol-outreach/template/campaign/CONVERSATIONS/.gitkeep +0 -0
- package/.claude/skills/kol-outreach/template/campaign/KOLS.md +6 -0
- package/.claude/skills/kol-outreach/template/campaign/PROGRESS.md +3 -0
- package/.claude/skills/kol-outreach/template/campaign/TEMPLATES.md +88 -0
- package/.claude/skills/kol-outreach/template/campaign/assets/.gitkeep +0 -0
- package/.claude/skills/kol-outreach/template/merchant/BRAND.md +36 -0
- package/.claude/skills/kol-outreach/template/merchant/CAMPAIGNS.md +6 -0
- package/.claude/skills/kol-outreach/template/merchant/MERCHANT_LIMITS.md +16 -0
- package/.claude/skills/kol-outreach/template/merchant/PROGRESS.md +4 -0
- package/.claude/skills/kol-outreach/template/merchant/README.md +20 -0
- package/.claude/skills/video-clone/SKILL.md +136 -429
- package/.claude/skills/video-clone/assets/phase-state-template.json +11 -0
- package/.claude/skills/video-clone/references/ffmpeg-commands.md +42 -0
- package/.claude/skills/video-clone/references/gate-enforcement.md +144 -0
- package/.claude/skills/video-clone/references/kling-api.md +52 -0
- package/.claude/skills/video-clone/references/prompt-template.md +71 -0
- package/.claude/skills/video-clone/references/url-parsing.md +32 -0
- package/.claude/skills/video-clone/references/workflow-system.md +92 -0
- package/.claude/skills/video-clone/scripts/_confirm.py +96 -0
- package/.claude/skills/video-clone/scripts/_confirm_test.py +125 -0
- package/.claude/skills/video-clone/scripts/_gate.py +162 -0
- package/.claude/skills/video-clone/scripts/_gate_e2e_test.py +226 -0
- package/.claude/skills/video-clone/scripts/_gate_test.py +148 -0
- package/.claude/skills/video-clone/scripts/_project.py +56 -0
- package/.claude/skills/video-clone/scripts/analyze_source.py +113 -0
- package/.claude/skills/video-clone/scripts/analyze_source_test.py +52 -0
- package/.claude/skills/video-clone/scripts/assemble.py +106 -0
- package/.claude/skills/video-clone/scripts/confirm.py +12 -0
- package/.claude/skills/video-clone/scripts/edit_first_frame.py +66 -0
- package/.claude/skills/video-clone/scripts/extract_frames.py +108 -0
- package/.claude/skills/video-clone/scripts/gen_video.py +59 -0
- package/.claude/skills/video-clone/scripts/init_project.py +103 -0
- package/.claude/skills/video-clone/scripts/init_project_test.py +106 -0
- package/.claude/skills/video-clone/scripts/kling_generate.py +182 -0
- package/.claude/skills/video-clone/scripts/preflight.py +95 -0
- package/.claude/skills/video-clone/scripts/preview.py +208 -0
- package/.claude/skills/video-clone/scripts/preview_test.py +169 -0
- package/.claude/skills/video-clone/scripts/save_workflow.py +129 -0
- package/.claude/skills/video-clone/scripts/save_workflow_test.py +106 -0
- package/.claude/skills/video-clone/scripts/status.py +202 -0
- package/.claude/skills/video-clone/scripts/status_test.py +174 -0
- package/package.json +2 -1
|
@@ -1,492 +1,199 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: video-clone
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use when user wants to clone/replicate a reference video with product swap, or generate a new video from product images + text descriptions. 触发场景:复刻视频(复刻/翻拍/仿拍/做同款/视频换产品/product swap/爆款复刻/video replication)、用户贴视频链接+产品图要求出同款视频、或用户提供图片/文字描述要求直接生成视频(生成视频/图生视频/做一个视频)。Pipeline is a script-based state machine under scripts/ — the generation scripts block until the user confirms the preview bundle. Requires `gen` CLI, video generation API via PiAPI, ffmpeg."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Video Clone
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
通过产品替换或文字描述,复刻源视频或生成全新视频。
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- "帮我分析一下这个视频" + 视频 → 只跑 Phase 1(分析+场景拆分)
|
|
14
|
-
- "换个首帧试试" → 回到 Phase 2 重跑
|
|
15
|
-
- "prompt 改一下" → 用户修改 prompt 后重跑 Phase 3
|
|
16
|
-
- "帮我生成一个视频" + 图片 + 描述 → **纯视频生成**(无源视频)
|
|
17
|
-
- "用这张图做个视频" + 图片 → 同上
|
|
10
|
+
> **PR #65 升级注意**:本版本采用单门 (single-gate) 模型。旧版三门
|
|
11
|
+
> (`plan_confirmed` / `prompt_confirmed` / `frame_confirmed`) 已废弃。
|
|
12
|
+
> 旧项目继续用旧脚本完成,新项目全部走本版本流程。
|
|
18
13
|
|
|
19
|
-
|
|
14
|
+
## 前置依赖
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
### 纯视频生成(无源视频)
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
图片 + 描述 → Claude 编写中文 6 段 prompt → 用户确认
|
|
31
|
-
→ 不需要音频 → gen video(Wan 2.6,~$0.02)
|
|
32
|
-
→ 需要音频 → Kling 3.0 API(~$1.00)
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## URL 解析
|
|
36
|
-
|
|
37
|
-
**不要用 WebFetch**(反爬/登录墙),按规则处理:
|
|
16
|
+
- **`gen` CLI** — `gen image`(首帧编辑)、`gen video`(I2V,无音频时使用)
|
|
17
|
+
- **视频生成 API via PiAPI** — 有音频/口型同步时使用。需要 `PIAPI_KEY` 环境变量
|
|
18
|
+
- **ffmpeg / ffprobe** — 场景检测、抽帧、后处理
|
|
19
|
+
- **Python ≥ 3.10** — 所有脚本运行时
|
|
20
|
+
- **freeimage.host** — 首帧上传时的公开 URL 托管(详见 [kling-api.md](references/kling-api.md))
|
|
38
21
|
|
|
39
|
-
|
|
40
|
-
|----------|------|
|
|
41
|
-
| TikTok `tiktok.com/@xxx/video/数字` | `scout tiktok video-detail <id>` → wget |
|
|
42
|
-
| TikTok 短链 `vm.tiktok.com/xxx` | `curl -sI` → Location → 提取 id |
|
|
43
|
-
| 抖音 `douyin.com/video/数字` | `scout douyin video-download <id>` → wget |
|
|
44
|
-
| 抖音短链 `v.douyin.com/xxx` | `scout douyin video-by-url "<url>"` |
|
|
45
|
-
| Instagram Reels | `scout instagram download-reel "<url>"` |
|
|
46
|
-
| 小红书视频 | `scout xhs note-detail <id>` → 视频链接 |
|
|
47
|
-
| 本地文件 | 直接使用 |
|
|
22
|
+
触发 skill 后第一步:运行 `python scripts/preflight.py`,确认上述依赖。
|
|
48
23
|
|
|
49
|
-
##
|
|
24
|
+
## 脚本 Pipeline 一览
|
|
50
25
|
|
|
51
|
-
|
|
26
|
+
单门模型:所有 prep 脚本自由运行,preview 之后只有一个 GATE。
|
|
52
27
|
|
|
53
28
|
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
29
|
+
preflight.py
|
|
30
|
+
↓
|
|
31
|
+
init_project.py (Phase 0 — 创建项目目录 + 状态文件)
|
|
32
|
+
↓
|
|
33
|
+
analyze_source.py (Phase 1, 复刻才需要)
|
|
34
|
+
extract_frames.py (Phase 1, 复刻才需要)
|
|
35
|
+
↓
|
|
36
|
+
Claude 分析帧网格,写 prompt.md
|
|
37
|
+
edit_first_frame.py (Phase 2, 复刻才需要)
|
|
38
|
+
写 cost.json (可选,估算成本)
|
|
39
|
+
↓
|
|
40
|
+
preview.py (汇总所有 prep 产物 → preview_vN.md)
|
|
41
|
+
↓
|
|
42
|
+
[展示 preview 给用户,等待确认]
|
|
43
|
+
↓
|
|
44
|
+
confirm.py --quote "<用户原话>" ← 唯一 GATE
|
|
45
|
+
↓
|
|
46
|
+
kling_generate.py (Phase 3, 有音频)
|
|
47
|
+
gen_video.py (Phase 3, 无音频)
|
|
48
|
+
↓
|
|
49
|
+
assemble.py (Phase 4 — 标准化/拼接)
|
|
50
|
+
↓
|
|
51
|
+
save_workflow.py (Phase 5 — 可选,效果好时沉淀)
|
|
70
52
|
```
|
|
71
53
|
|
|
72
|
-
|
|
54
|
+
`kling_generate.py`、`gen_video.py`、`save_workflow.py` 启动时调用
|
|
55
|
+
`require_gate("preview_confirmed")`,未确认就 exit 1 并打印
|
|
56
|
+
`[HARD-GATE BLOCKED]`。详见 [gate-enforcement.md](references/gate-enforcement.md)。
|
|
73
57
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
→ 用户确认或编辑 prompt.md → "视频生成中..." → 保存到 videos/
|
|
79
|
-
→ 交付 → 更新 log.md 结果
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
58
|
+
<HARD-GATE>
|
|
59
|
+
**Gate 由脚本机械强制,不是文本约定。** 任何绕过 gate 的方式都会留下证据:
|
|
60
|
+
1. 手工编辑 `.state/phase.json` — history 字段会显示断点
|
|
61
|
+
2. 伪造 `--quote` 调用 `confirm.py` — user_quote 字段留痕,事后可倒查
|
|
83
62
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
1. 首帧质量决定一切 — 自动选产品最清晰+手部最自然的帧
|
|
88
|
-
2. 让模型做简单的事 — 产品保持静止,人做简单动作
|
|
89
|
-
3. Prompt 质量 = 视频质量 — 必须打印给用户,用户可能修改
|
|
90
|
-
4. 永远不覆盖文件 — 所有产物版本化命名,保留完整迭代历史
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## 项目目录与文件管理
|
|
96
|
-
|
|
97
|
-
所有产物保存在 `gen-output/video-clone/{project}/`,`{project}` 由产品名或任务简称命名(如 `fishing-scale`、`car-creeper`)。
|
|
98
|
-
|
|
99
|
-
### 新任务 vs 修改已有任务
|
|
100
|
-
|
|
101
|
-
```
|
|
102
|
-
"帮我复刻这个视频" + 新产品图 → ls gen-output/video-clone/ → 新建 {project}/ 目录
|
|
103
|
-
"帮我做另一个视频" + 新素材 → 新建 {project}/ 目录
|
|
104
|
-
"换个首帧试试" / "prompt 改一下" → 继续当前 {project}/ 目录,v{N}+1
|
|
105
|
-
"上次那个电子秤视频再改改" → 进入已有 fishing-scale/ 目录,读 log.md 续接
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**判断逻辑**:有新源视频或新产品 → 新目录;改 prompt/换 seed/重跑 → 同目录递增版本。
|
|
109
|
-
|
|
110
|
-
### 目录结构
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
gen-output/video-clone/{project}/
|
|
114
|
-
├── source/ ← 源素材(只读)
|
|
115
|
-
│ ├── source_video.mp4
|
|
116
|
-
│ └── product.jpg
|
|
117
|
-
├── frames/ ← 抽帧 + 编辑首帧(版本化)
|
|
118
|
-
│ ├── source_t15.0s.jpg ← 选中的源帧
|
|
119
|
-
│ ├── frame_v1_s42.png ← 首帧编辑 v1(seed=42)
|
|
120
|
-
│ ├── frame_v2_s43.png ← 首帧编辑 v2(seed=43)
|
|
121
|
-
│ ├── scene1_frame_v1_s42.png ← [多片段] 场景1首帧
|
|
122
|
-
│ └── grid.jpg ← 帧网格
|
|
123
|
-
├── videos/ ← 视频产物(版本化)
|
|
124
|
-
│ ├── video_v1_10s.mp4 ← 视频 v1
|
|
125
|
-
│ ├── video_v2_10s.mp4 ← 视频 v2(改了prompt)
|
|
126
|
-
│ ├── scene1_v1_5s.mp4 ← [多片段] 场景1视频
|
|
127
|
-
│ └── final_v2.mp4 ← 最终交付版本
|
|
128
|
-
├── prompt.md ← 当前 prompt(用户可直接编辑)
|
|
129
|
-
└── log.md ← 迭代日志(版本历史 + 用户反馈)
|
|
130
|
-
```
|
|
63
|
+
**USER GATE 不可被用户单方面取消。** 即使用户说"不要问问题/我信任你/自己判断",
|
|
64
|
+
仍必须展示 preview bundle 并等待确认。用户可以说"可以,开始"以确认,但不能
|
|
65
|
+
预先豁免整个 GATE 机制。
|
|
131
66
|
|
|
132
|
-
|
|
67
|
+
每个 Phase 产物必须版本化命名(脚本通过 `_project.next_version()` 自动处理),
|
|
68
|
+
绝不覆盖已有文件。
|
|
69
|
+
</HARD-GATE>
|
|
133
70
|
|
|
134
|
-
|
|
135
|
-
- 视频:`video_v{N}_{duration}s.mp4`,多片段 `scene{M}_v{N}_{duration}s.mp4`
|
|
136
|
-
- 最终:`final_v{N}.mp4`(指向最终采用的版本)
|
|
137
|
-
- **v{N} 递增,绝不覆盖**
|
|
71
|
+
## Rationalization Counter
|
|
138
72
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
Claude 分析后写入,用户确认或修改后,Phase 3 从此文件读取 prompt 生成视频。
|
|
142
|
-
|
|
143
|
-
```markdown
|
|
144
|
-
# fishing-scale — Prompt
|
|
145
|
-
|
|
146
|
-
### 视觉风格
|
|
147
|
-
竖屏手持vlog,自然饱和色彩,明亮日光,无滤镜,纪实感。
|
|
148
|
-
|
|
149
|
-
### 场景叙述
|
|
150
|
-
阳光白天,戴眼镜、深蓝头巾、黑色运动上衣的女子跪坐沙滩...
|
|
151
|
-
|
|
152
|
-
### 摄影技术
|
|
153
|
-
...
|
|
154
|
-
|
|
155
|
-
### 动作清单
|
|
156
|
-
...
|
|
157
|
-
|
|
158
|
-
### 对话
|
|
159
|
-
...
|
|
160
|
-
|
|
161
|
-
### 背景声音
|
|
162
|
-
...
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
**prompt.md 工作流**:
|
|
166
|
-
1. Claude 分析 → 写入 prompt.md → 打印给用户
|
|
167
|
-
2. 用户说"OK" → 直接用;用户说"改一下动作" → 用户自行编辑 prompt.md 或告诉 Claude 改
|
|
168
|
-
3. Phase 3 从 prompt.md 读取生成视频
|
|
169
|
-
4. 需要重跑时:修改 prompt.md → 旧版本自动记录到 log.md
|
|
170
|
-
|
|
171
|
-
### 迭代日志(log.md)
|
|
172
|
-
|
|
173
|
-
记录每次迭代的版本快照。**不存完整 prompt**(prompt.md 是唯一来源),只记变更摘要。
|
|
174
|
-
|
|
175
|
-
```markdown
|
|
176
|
-
# fishing-scale — Video Clone Log
|
|
177
|
-
Created: 2026-04-10 14:30
|
|
178
|
-
|
|
179
|
-
## v1 — 2026-04-10 14:30
|
|
180
|
-
- **首帧**: frame_v1_s42.png ✅ 用户确认
|
|
181
|
-
- **Prompt**: 初始版本(见 prompt.md)
|
|
182
|
-
- **视频**: video_v1_10s.mp4
|
|
183
|
-
- **结果**: 手部变形,用户要求改 prompt
|
|
184
|
-
|
|
185
|
-
## v2 — 2026-04-10 15:10
|
|
186
|
-
- **首帧**: 复用 v1(frame_v1_s42.png)
|
|
187
|
-
- **Prompt 修改**: 动作清单删除"举起电子秤",改为"手指轻触电子秤"
|
|
188
|
-
- **视频**: video_v2_10s.mp4
|
|
189
|
-
- **结果**: ✅ 用户满意 → final_v2.mp4
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**日志规则**:
|
|
193
|
-
- 首帧没变就写"复用 vX",变了就写新文件名
|
|
194
|
-
- Prompt 修改只记差异摘要(完整内容始终在 prompt.md)
|
|
195
|
-
- 结果必须记录用户反馈(满意/不满意+原因)
|
|
196
|
-
- 跨会话续接时,先读 log.md 获取上次版本号,再读 prompt.md 获取当前 prompt
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## Pipeline 总览
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
单片段:源视频 → 分析 → gen image 首帧编辑 → I2V → 后处理 → 成品
|
|
204
|
-
多片段:源视频 → 场景拆分 → 每段 gen image 首帧 → 每段 I2V → 拼接 → 成品
|
|
205
|
-
纯生成:图片 → prompt → gen video(无音频) 或 Kling(有音频) → 成品
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
## 工具分工
|
|
209
|
-
|
|
210
|
-
| 工具 | 职责 |
|
|
211
|
-
|------|------|
|
|
212
|
-
| **Claude Opus** | 逐帧分析 → 中文 6 段 prompt;纯生成时根据用户描述编写 prompt |
|
|
213
|
-
| **gen image** | 首帧编辑(多图输入:`-i 源帧 -i 产品图`)|
|
|
214
|
-
| **gen video** | Wan 2.6 I2V(不需要音频时)|
|
|
215
|
-
| **Kling 3.0**(PiAPI) | I2V(需要音频时,口型同步)|
|
|
216
|
-
| **ffmpeg** | 抽帧、场景拆分、后处理、拼接 |
|
|
217
|
-
|
|
218
|
-
---
|
|
73
|
+
以下是最常见的"合理化借口"及其反驳。遇到这些想法时必须 STOP。
|
|
219
74
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
切换点 ≤1 → 单片段 | ≥2 → 多片段(过滤 <0.5s 片段)
|
|
230
|
-
|
|
231
|
-
### 1.2 抽帧 + 帧网格
|
|
232
|
-
|
|
233
|
-
**单片段**:等间距抽 10 帧 → 5×2 网格。
|
|
234
|
-
**多片段**:每段 3-10 帧 → 每段网格 + 总网格。标注时间戳。
|
|
235
|
-
|
|
236
|
-
### 1.3 Claude Opus 分析(核心)
|
|
75
|
+
| Claude 的想法 | 现实 |
|
|
76
|
+
|---|---|
|
|
77
|
+
| "我只是在做 Phase 0 分析,下载视频不算执行" | 下载 = 工具调用。分析基于用户提供的元数据,不是基于已下载的文件 |
|
|
78
|
+
| "用户说'急用'/'现在就开始',所以可以跳过确认" | 紧迫感不是跳过 GATE 的理由。越急越要快速对齐,避免返工 |
|
|
79
|
+
| "用户说'不要问问题,自己判断'" | 覆盖提问,**不覆盖** preview 展示。自己判断后仍要出 preview |
|
|
80
|
+
| "信息已经完整了,preview 只是走过场" | preview 是用户发现隐含错误的最后机会 |
|
|
81
|
+
| "我直接运行 kling_generate 只是测试" | 脚本 exit 1,测试什么都看不到 |
|
|
82
|
+
| "我 `python -c 'import _gate; _gate.set_gate(...)'` 自己设 gate" | history 字段暴露没走 confirm.py 正常路径 |
|
|
83
|
+
| "prep 脚本没有 gate,所以我可以随意运行" | prep 脚本确实无 gate — 但 **preview → confirm** 这一步仍是必须的 |
|
|
237
84
|
|
|
238
|
-
|
|
85
|
+
## Phase 0: 理解需求 + 匹配 Workflow
|
|
239
86
|
|
|
240
|
-
|
|
241
|
-
- 精确描述产品外观(颜色/形状/特征,从产品图提取)
|
|
242
|
-
- 精确描述背景和光线(从源帧提取)
|
|
87
|
+
**在动手之前,先搞清楚用户到底要什么,再看有没有现成的好方案。**
|
|
243
88
|
|
|
244
|
-
|
|
89
|
+
快速判断任务类型:有源视频 + 产品图 → 视频复刻;无源视频 → 纯视频生成。
|
|
245
90
|
|
|
246
|
-
|
|
91
|
+
**仅做轻量元数据识别,不执行工具调用**。不下载视频、不调 ffprobe、不抽帧。
|
|
247
92
|
|
|
248
|
-
|
|
93
|
+
按需提问(不一次全问):产品是什么、替换目标、音频需求(有音频 ~$1,无音频 ~$0.02)、时长期望。
|
|
249
94
|
|
|
250
|
-
|
|
95
|
+
先查 `gen-output/video-clone/workflows/README.md` — 完全匹配 → 复用;部分匹配 → 调整;
|
|
96
|
+
无匹配 → 走通用 pipeline。详见 [workflow-system.md](references/workflow-system.md)。
|
|
251
97
|
|
|
252
|
-
## Phase 2:
|
|
98
|
+
## Phase 1-2: Prep(自主运行,无 gate)
|
|
253
99
|
|
|
254
|
-
|
|
100
|
+
Prep 阶段所有脚本均无 gate,可自主运行:
|
|
255
101
|
|
|
256
102
|
```bash
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
# 不满意 → 换 seed: frame_v2_s43.png,绝不覆盖 v1
|
|
103
|
+
python scripts/init_project.py --name <slug> --task-type video_clone
|
|
104
|
+
python scripts/analyze_source.py --project <slug> --source <path>
|
|
105
|
+
python scripts/extract_frames.py --project <slug> --source <path>
|
|
106
|
+
# Claude 分析帧网格,写 prompt.md
|
|
107
|
+
python scripts/edit_first_frame.py --project <slug> --image <frame> --product <img>
|
|
108
|
+
# 写 cost.json(可选)
|
|
109
|
+
python scripts/preview.py --project <slug>
|
|
265
110
|
```
|
|
266
111
|
|
|
267
|
-
|
|
112
|
+
`preview.py` 检查所有 prep 产物是否齐全,输出 `preview_vN.md`(六节)。
|
|
268
113
|
|
|
269
|
-
|
|
114
|
+
**[USER GATE] 把 preview 展示给用户,等待确认,然后运行:**
|
|
270
115
|
|
|
271
116
|
```bash
|
|
272
|
-
|
|
273
|
-
the reference image - 颜色/logo/特征] [场景] Vertical 9:16. Photorealistic." \
|
|
274
|
-
-i product.jpg \
|
|
275
|
-
-W 576 -H 1024 -s 42 \
|
|
276
|
-
-o gen-output/video-clone/{project}/frames/scene1_frame_v1_s42.png
|
|
277
|
-
Read gen-output/video-clone/{project}/frames/scene1_frame_v1_s42.png
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
⚠️ 每段 prompt 中产品描述重复(防遗忘),人物外貌跨段一致
|
|
281
|
-
|
|
282
|
-
### 首帧质检(展示给用户确认)
|
|
283
|
-
|
|
117
|
+
python scripts/confirm.py --project <slug> --quote "<用户原话>"
|
|
284
118
|
```
|
|
285
|
-
□ 产品清晰? □ 位置自然? □ 人物保持? □ 背景一致?
|
|
286
|
-
不合格 → 换 seed(-s 43) → 调 prompt → 重新确认
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## Phase 3: I2V 视频生成
|
|
292
119
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
| 场景 | 工具 | 音频 |
|
|
296
|
-
|------|------|------|
|
|
297
|
-
| 复刻(默认) | Kling 3.0 API | 有(口型同步) |
|
|
298
|
-
| 纯生成 + 需要音频 | Kling 3.0 API | 有 |
|
|
299
|
-
| 纯生成 + 不需要音频 | gen video | 无 |
|
|
300
|
-
|
|
301
|
-
### 3.2 gen video(Wan 2.6,不需要音频时)
|
|
120
|
+
## Phase 3-5: 生成 + 后处理 + 沉淀
|
|
302
121
|
|
|
303
122
|
```bash
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
Read gen-output/video-clone/{project}/videos/video_v1_10s.mp4
|
|
309
|
-
# 重跑 → video_v2_10s.mp4,绝不覆盖
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### 3.3 Kling 3.0 API(需要音频时)
|
|
313
|
-
|
|
314
|
-
**Step 1: 上传首帧获取公开 URL**(Kling 不接受 base64,需要 URL)
|
|
315
|
-
|
|
316
|
-
```python
|
|
317
|
-
import requests, base64
|
|
318
|
-
|
|
319
|
-
img_b64 = base64.b64encode(open('edited_frame.png', 'rb').read()).decode()
|
|
320
|
-
resp = requests.post('https://freeimage.host/api/1/upload', data={
|
|
321
|
-
'key': '6d207e02198a847aa98d0a2a901485a5',
|
|
322
|
-
'action': 'upload',
|
|
323
|
-
'source': img_b64,
|
|
324
|
-
'format': 'json',
|
|
325
|
-
})
|
|
326
|
-
img_url = resp.json()['image']['url']
|
|
327
|
-
# ⚠️ catbox.moe 不可用(PiAPI 服务器访问不了)
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
**Step 2: 提交生成任务**
|
|
331
|
-
|
|
332
|
-
```python
|
|
333
|
-
resp = requests.post('https://api.piapi.ai/api/v1/task',
|
|
334
|
-
headers={'x-api-key': PIAPI_KEY, 'Content-Type': 'application/json'},
|
|
335
|
-
json={
|
|
336
|
-
'model': 'kling',
|
|
337
|
-
'task_type': 'video_generation',
|
|
338
|
-
'input': {
|
|
339
|
-
'prompt': motion_prompt,
|
|
340
|
-
'negative_prompt': 'slow motion, dreamy, ethereal, cinematic, blurry, '
|
|
341
|
-
'distorted, deformed hands, extra fingers',
|
|
342
|
-
'image_url': img_url,
|
|
343
|
-
'duration': 10, # 或 5(多片段时)
|
|
344
|
-
'aspect_ratio': '9:16',
|
|
345
|
-
'mode': 'std', # 720p
|
|
346
|
-
'version': '3.0',
|
|
347
|
-
'cfg_scale': 0.5, # ⚠️ 必须 float!
|
|
348
|
-
'enable_audio': True,
|
|
349
|
-
},
|
|
350
|
-
'config': {'service_mode': 'public'},
|
|
351
|
-
}, timeout=60)
|
|
352
|
-
task_id = resp.json()['data']['task_id']
|
|
353
|
-
```
|
|
123
|
+
# Phase 3 — 视频生成(需要 preview_confirmed)
|
|
124
|
+
python scripts/kling_generate.py --project <slug> --frame frames/frame_vN.png
|
|
125
|
+
# 或无音频版本:
|
|
126
|
+
python scripts/gen_video.py --project <slug> --frame frames/frame_vN.png
|
|
354
127
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
```python
|
|
358
|
-
import time
|
|
359
|
-
while True:
|
|
360
|
-
r = requests.get(f'https://api.piapi.ai/api/v1/task/{task_id}',
|
|
361
|
-
headers={'x-api-key': PIAPI_KEY})
|
|
362
|
-
d = r.json().get('data', {})
|
|
363
|
-
status = d.get('status', '')
|
|
364
|
-
if status == 'completed': # ⚠️ 小写!
|
|
365
|
-
video_url = d['output']['video'] # ⚠️ 3.0 用 video,2.6 用 video_url
|
|
366
|
-
break
|
|
367
|
-
if status == 'failed':
|
|
368
|
-
raise RuntimeError(d.get('error', {}))
|
|
369
|
-
time.sleep(15)
|
|
370
|
-
```
|
|
128
|
+
# Phase 4 — 后处理
|
|
129
|
+
python scripts/assemble.py --project <slug> --single videos/video_vN.mp4
|
|
371
130
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
try:
|
|
377
|
-
data = requests.get(video_url, timeout=300).content
|
|
378
|
-
open('gen-output/video-clone/{project}/videos/video_v1_10s.mp4', 'wb').write(data)
|
|
379
|
-
break
|
|
380
|
-
# 重跑 → video_v2_10s.mp4,绝不覆盖
|
|
381
|
-
except Exception:
|
|
382
|
-
time.sleep(5)
|
|
131
|
+
# Phase 5 — 沉淀(可选)
|
|
132
|
+
python scripts/save_workflow.py --project <slug> \
|
|
133
|
+
--name <workflow-slug> --scene "<适用场景>" \
|
|
134
|
+
--rating <1-5> --strategy "<关键策略>"
|
|
383
135
|
```
|
|
384
136
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
**复刻时**:Claude Opus 分析源帧后生成。**纯生成时**:Claude 根据用户描述编写。
|
|
388
|
-
两种都写入 `prompt.md` 并打印给用户,用户可直接编辑文件。Phase 3 从 `prompt.md` 读取。
|
|
389
|
-
|
|
390
|
-
```
|
|
391
|
-
### 视觉风格
|
|
392
|
-
[拍摄设备感 + 画面质感 + 色彩方案 + 光线 + 氛围]
|
|
393
|
-
|
|
394
|
-
### 场景叙述
|
|
395
|
-
[时间地点 + 人物外貌 + 产品描述(重复颜色/特征) + 背景环境]
|
|
396
|
-
|
|
397
|
-
### 摄影技术
|
|
398
|
-
[景别 + 运镜 + 焦段 + 景深 + 光线] 情绪:[...]
|
|
137
|
+
## 铁律
|
|
399
138
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
139
|
+
1. 先理解再动手 — 出 preview 前先跑完所有 prep 脚本
|
|
140
|
+
2. 先查 workflow 再造轮子 — 已有经验不要浪费
|
|
141
|
+
3. 首帧质量决定一切 — 自动选产品最清晰+手部最自然的帧
|
|
142
|
+
4. Prompt 质量 = 视频质量 — preview 里展示给用户,用户可能修改
|
|
143
|
+
5. 永远不覆盖文件 — 脚本通过 next_version() 自动 v{N} 递增
|
|
144
|
+
6. 不要自己编辑 .state/phase.json — 还不如走 confirm.py 正常路径
|
|
403
145
|
|
|
404
|
-
|
|
405
|
-
- [语言和风格]
|
|
146
|
+
## 项目目录
|
|
406
147
|
|
|
407
|
-
### 背景声音
|
|
408
|
-
- [环境音 + 人声 + 无背景音乐]
|
|
409
148
|
```
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
### 单片段
|
|
419
|
-
|
|
420
|
-
```bash
|
|
421
|
-
# video_v{N} → final_v{N}
|
|
422
|
-
ffmpeg -y -i gen-output/video-clone/{project}/videos/video_v1_10s.mp4 \
|
|
423
|
-
-r 30 -c:v libx264 -crf 18 -c:a aac -b:a 192k \
|
|
424
|
-
gen-output/video-clone/{project}/videos/final_v1.mp4
|
|
149
|
+
gen-output/video-clone/
|
|
150
|
+
├── workflows/ ← Workflow 经验库(README.md 索引)
|
|
151
|
+
└── {project}/
|
|
152
|
+
├── .state/phase.json ← Gate 状态机
|
|
153
|
+
├── source/ ← 原始素材 + analysis_vN.json
|
|
154
|
+
├── frames/ ← extract_vN/ + frame_vN.png
|
|
155
|
+
├── videos/ ← video_vN.mp4 + final_vN.mp4
|
|
156
|
+
├── prompt.md cost.json preview_vN.md log.md
|
|
425
157
|
```
|
|
426
158
|
|
|
427
|
-
|
|
159
|
+
新任务 → 新目录;改 prompt/换 seed → 同目录 v{N}+1。
|
|
160
|
+
跨会话续接:先 `python scripts/status.py --project <slug>` 看当前状态和下一步。
|
|
428
161
|
|
|
429
|
-
|
|
430
|
-
# 标准化每个 clip
|
|
431
|
-
ffmpeg -y -i gen-output/video-clone/{project}/videos/scene1_v1_5s.mp4 \
|
|
432
|
-
-vf scale=720:1280 -r 30 -c:v libx264 -crf 18 -c:a aac -b:a 128k scene1_norm.mp4
|
|
433
|
-
|
|
434
|
-
# 拼接 → final_v{N}
|
|
435
|
-
echo "file 'scene1_norm.mp4'
|
|
436
|
-
file 'scene2_norm.mp4'" > concat_list.txt
|
|
437
|
-
ffmpeg -y -f concat -safe 0 -i concat_list.txt -c:v libx264 -crf 18 -c:a aac -b:a 192k \
|
|
438
|
-
gen-output/video-clone/{project}/videos/final_v1.mp4
|
|
439
|
-
```
|
|
162
|
+
## 工具分工
|
|
440
163
|
|
|
441
|
-
|
|
164
|
+
| 工具 | 脚本 | 职责 |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| Claude | — | 需求理解 + 逐帧分析 → 中文 6 段 prompt |
|
|
167
|
+
| gen image | `edit_first_frame.py` | 首帧编辑(双图模式) |
|
|
168
|
+
| gen video | `gen_video.py` | I2V(不需要音频) |
|
|
169
|
+
| 视频生成 API | `kling_generate.py` | 有音频/口型同步。详见 [kling-api.md](references/kling-api.md) |
|
|
170
|
+
| ffmpeg | `analyze_source.py` / `extract_frames.py` / `assemble.py` | 抽帧、场景检测、后处理 |
|
|
442
171
|
|
|
443
|
-
|
|
172
|
+
**不要在回复中提及具体模型名称**(如 "Kling 3.0"、"Wan 2.6")。
|
|
173
|
+
只说"视频生成中..."或"已提交生成任务"。
|
|
444
174
|
|
|
445
|
-
|
|
446
|
-
□ 产品可辨? □ 手部自然? □ 物理正确? □ 人脸稳定? □ 背景一致? □ 音频正常?
|
|
447
|
-
□ [多片段] 过渡自然?产品跨段一致?
|
|
448
|
-
不合格 → 调 prompt / 换 seed 重跑(可只重跑问题片段)
|
|
449
|
-
```
|
|
175
|
+
## 首帧编辑策略
|
|
450
176
|
|
|
451
|
-
|
|
177
|
+
**单片段**:`edit_first_frame.py` 用双图(`-i 源帧 -i 产品图`),保持场景只替换产品。
|
|
178
|
+
**多片段**:每段仅 `-i 产品图`,prompt 描述完整场景,产品描述跨段重复。
|
|
452
179
|
|
|
453
|
-
##
|
|
180
|
+
## Anti-Pattern
|
|
454
181
|
|
|
455
|
-
|
|
|
182
|
+
| 你在想... | 应该做的 |
|
|
456
183
|
|---|---|
|
|
184
|
+
| 用户给了素材直接开干 | **先 preflight + 跑完 prep + 出 preview + confirm.py** |
|
|
185
|
+
| 不看 workflow 库直接走通用 | 先查 `workflows/README.md` |
|
|
457
186
|
| 直接取 t=1s 当首帧 | 自动选产品最清晰的帧 |
|
|
458
|
-
| prompt
|
|
459
|
-
|
|
|
460
|
-
|
|
|
461
|
-
|
|
|
462
|
-
|
|
|
463
|
-
|
|
|
464
|
-
| prompt 超 2500 字符 | 精简到 1200-2000 |
|
|
465
|
-
| 用 catbox.moe 托管图片 | 用 freeimage.host |
|
|
466
|
-
| 本地直接调 API | 通过服务器中转 |
|
|
467
|
-
| 覆盖之前生成的文件 | v{N} 递增命名,保留全部历史 |
|
|
468
|
-
| 不写 log.md | 每次操作必须追加日志 |
|
|
469
|
-
|
|
470
|
-
---
|
|
187
|
+
| prompt 不给用户看 | **必须在 preview 里展示,用户可能修改** |
|
|
188
|
+
| 跳过 preview 直接 confirm | preview.py 会验证所有 prep 产物是否齐全 |
|
|
189
|
+
| 告诉用户具体模型名称 | 只说 "视频生成中..." 不透露底层模型 |
|
|
190
|
+
| 做出好效果不保存 workflow | **效果好 + 新场景 = 必须沉淀** |
|
|
191
|
+
| 覆盖之前生成的文件 | 脚本自动 v{N} 递增 |
|
|
192
|
+
| 把 `--quote "ok"` 当成真实确认 | 伪造 quote 会在 history 留痕,事后可倒查 |
|
|
471
193
|
|
|
472
194
|
## 已知限制
|
|
473
195
|
|
|
474
|
-
-
|
|
475
|
-
-
|
|
476
|
-
-
|
|
477
|
-
|
|
478
|
-
## 实战参考
|
|
479
|
-
|
|
480
|
-
**demo1 沙滩电子秤**:t=1s 无产品→失败,改 t=15s→完美。首帧选择 + prompt 质量 >> 一切。
|
|
481
|
-
|
|
482
|
-
**demo2 汽车躺板-单片段**:PiAPI FLUX 单图+一句话=⭐⭐,BFL FLUX-PRO 双图+6段 prompt=⭐⭐⭐⭐⭐。
|
|
483
|
-
|
|
484
|
-
**demo3 汽车躺板-多片段**:18s 源视频 4 场景 → 拆分 → 每段 gen image + Kling 5s → 拼接 20s。关键:产品描述跨段一致。
|
|
485
|
-
|
|
486
|
-
## 重要提醒
|
|
487
|
-
|
|
488
|
-
1. **BFL 轮询 "Task not found"** 持续约 60s,正常,继续轮询
|
|
489
|
-
2. **Kling enable_audio 只有 3.0 支持**
|
|
490
|
-
3. **Kling 状态小写 "completed"**,输出字段 `output.video`(3.0)
|
|
491
|
-
4. **国内网络通过服务器中转** API,本地大 payload 会断连
|
|
492
|
-
5. **freeimage.host key**: `6d207e02198a847aa98d0a2a901485a5`
|
|
196
|
+
- 单段最长 10s,多段需拼接
|
|
197
|
+
- 动作模型自编,不还原源视频动作序列
|
|
198
|
+
- PiAPI CDN 不稳定,`kling_generate.py` 内置 3 次重试
|
|
199
|
+
- 平台解析(TikTok/抖音/Instagram/小红书)仍需手动调 `scout` 命令,不在脚本 pipeline 里(详见 [url-parsing.md](references/url-parsing.md))
|