@renoise/video-maker 0.1.0
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-plugin/plugin.json +5 -0
- package/README.md +50 -0
- package/hooks/hooks.json +16 -0
- package/hooks/session-start.sh +17 -0
- package/lib/gemini.ts +49 -0
- package/package.json +22 -0
- package/skills/director/SKILL.md +272 -0
- package/skills/director/references/narrative-pacing.md +257 -0
- package/skills/director/references/style-library.md +179 -0
- package/skills/product-sheet-generate/SKILL.md +75 -0
- package/skills/renoise-gen/SKILL.md +362 -0
- package/skills/renoise-gen/references/api-endpoints.md +138 -0
- package/skills/renoise-gen/references/video-capabilities.md +524 -0
- package/skills/renoise-gen/renoise-cli.mjs +723 -0
- package/skills/scene-generate/SKILL.md +52 -0
- package/skills/short-film-editor/SKILL.md +479 -0
- package/skills/short-film-editor/examples/mystery-package-4shot.md +260 -0
- package/skills/short-film-editor/references/continuity-guide.md +170 -0
- package/skills/short-film-editor/scripts/analyze-beats.py +271 -0
- package/skills/short-film-editor/scripts/batch-generate.sh +150 -0
- package/skills/short-film-editor/scripts/generate-storyboard-html.ts +714 -0
- package/skills/short-film-editor/scripts/split-grid.sh +70 -0
- package/skills/tiktok-content-maker/SKILL.md +143 -0
- package/skills/tiktok-content-maker/examples/dress-demo.md +86 -0
- package/skills/tiktok-content-maker/references/ecom-prompt-guide.md +261 -0
- package/skills/tiktok-content-maker/scripts/analyze-images.ts +122 -0
- package/skills/video-download/SKILL.md +161 -0
- package/skills/video-download/scripts/download-video.sh +91 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Split a storyboard grid image into individual panel images.
|
|
4
|
+
# Uses ImageMagick to crop each cell from an NxM grid.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# bash split-grid.sh <grid_image> <output_dir> <rows> <cols>
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
# bash split-grid.sh grid.png storyboard/ 2 4
|
|
11
|
+
# → storyboard/S1.png, S2.png, S3.png, ..., S8.png
|
|
12
|
+
#
|
|
13
|
+
# Dependencies: ImageMagick (brew install imagemagick)
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
GRID_IMAGE="${1:-}"
|
|
18
|
+
OUTPUT_DIR="${2:-}"
|
|
19
|
+
ROWS="${3:-2}"
|
|
20
|
+
COLS="${4:-4}"
|
|
21
|
+
|
|
22
|
+
if [[ -z "$GRID_IMAGE" || -z "$OUTPUT_DIR" ]]; then
|
|
23
|
+
echo "Usage: split-grid.sh <grid_image> <output_dir> [rows] [cols]"
|
|
24
|
+
echo "Example: split-grid.sh grid.png storyboard/ 2 4"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if ! command -v magick &>/dev/null && ! command -v convert &>/dev/null; then
|
|
29
|
+
echo "Error: ImageMagick not found. Install with: brew install imagemagick"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Determine ImageMagick command (v7: magick, v6: convert/identify)
|
|
34
|
+
if command -v magick &>/dev/null; then
|
|
35
|
+
IDENTIFY="magick identify"
|
|
36
|
+
CONVERT="magick"
|
|
37
|
+
else
|
|
38
|
+
IDENTIFY="identify"
|
|
39
|
+
CONVERT="convert"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
mkdir -p "$OUTPUT_DIR"
|
|
43
|
+
|
|
44
|
+
# Get image dimensions
|
|
45
|
+
DIMS=$($IDENTIFY -format "%wx%h" "$GRID_IMAGE")
|
|
46
|
+
IMG_W=$(echo "$DIMS" | cut -dx -f1)
|
|
47
|
+
IMG_H=$(echo "$DIMS" | cut -dx -f2)
|
|
48
|
+
|
|
49
|
+
CELL_W=$((IMG_W / COLS))
|
|
50
|
+
CELL_H=$((IMG_H / ROWS))
|
|
51
|
+
|
|
52
|
+
echo "Grid: ${IMG_W}x${IMG_H}, Layout: ${ROWS}x${COLS}, Cell: ${CELL_W}x${CELL_H}"
|
|
53
|
+
|
|
54
|
+
INDEX=1
|
|
55
|
+
for row in $(seq 0 $((ROWS - 1))); do
|
|
56
|
+
for col in $(seq 0 $((COLS - 1))); do
|
|
57
|
+
X=$((col * CELL_W))
|
|
58
|
+
Y=$((row * CELL_H))
|
|
59
|
+
OUT_FILE="${OUTPUT_DIR}/S${INDEX}.png"
|
|
60
|
+
|
|
61
|
+
$CONVERT "$GRID_IMAGE" -crop "${CELL_W}x${CELL_H}+${X}+${Y}" +repage "$OUT_FILE"
|
|
62
|
+
|
|
63
|
+
SIZE=$(ls -lh "$OUT_FILE" | awk '{print $5}')
|
|
64
|
+
echo " S${INDEX}: ${CELL_W}x${CELL_H} @ +${X}+${Y} → ${OUT_FILE} (${SIZE})"
|
|
65
|
+
|
|
66
|
+
INDEX=$((INDEX + 1))
|
|
67
|
+
done
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
echo "Done: $((INDEX - 1)) panels extracted"
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tiktok-content-maker
|
|
3
|
+
description: >
|
|
4
|
+
TikTok e-commerce short video script generator. Analyzes product photos,
|
|
5
|
+
generates 15s video scripts with video prompts and English dialogue.
|
|
6
|
+
Use when user says "TikTok product video", "ecommerce video", "电商视频",
|
|
7
|
+
"带货视频", "商品视频", "拍商品". Do NOT use for non-ecommerce videos or
|
|
8
|
+
general creative direction (use director instead).
|
|
9
|
+
allowed-tools: Bash, Read
|
|
10
|
+
metadata:
|
|
11
|
+
author: renoise
|
|
12
|
+
version: 0.1.0
|
|
13
|
+
category: video-production
|
|
14
|
+
tags: [product, ecommerce, tiktok]
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Content Maker — 电商短视频脚本 + 视频生成
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
电商短视频全流程工具:用户提供商品图(+ 可选模特图)→ 分析商品信息 → 生成 15 秒 TikTok 脚本(视频 prompt,含英文台词嵌入)→ 提交视频生成任务。
|
|
22
|
+
|
|
23
|
+
## Workflow
|
|
24
|
+
|
|
25
|
+
### Phase 1: 素材收集 & 商品分析
|
|
26
|
+
|
|
27
|
+
1. **收集素材路径**:向用户索要图片
|
|
28
|
+
- `商品图路径`(必需):产品主图。**最佳:干净白底纯产品图,无文字/标注/装饰**。有营销文字覆盖的图会干扰模型。
|
|
29
|
+
- `模特图路径`(可选,仅供分析参考):展示穿搭/使用效果的图。**注意:模特图仅用于理解产品使用方式,不上传到 Renoise**(隐私检测会拦截含真人面孔的图片)。
|
|
30
|
+
|
|
31
|
+
2. **分析商品信息**:
|
|
32
|
+
- 如果有 Gemini API 可用,调用 Gemini 分析:
|
|
33
|
+
```bash
|
|
34
|
+
cd ${CLAUDE_PLUGIN_ROOT} && npm install --silent && npx tsx ${CLAUDE_SKILL_DIR}/scripts/analyze-images.ts "<商品图路径>" "<模特图路径>"
|
|
35
|
+
```
|
|
36
|
+
- 也可以直接通过 Read 工具查看图片,人工分析商品信息
|
|
37
|
+
- 需要提取:商品类型、颜色、材质、卖点、品牌调性、适用场景
|
|
38
|
+
- **(关键)从使用场景图中理解产品的正确使用方式**:
|
|
39
|
+
- 用户的姿势是什么?(站/坐/躺/走)
|
|
40
|
+
- 产品放在身体哪个位置?(手持/地面/桌面/身体下方)
|
|
41
|
+
- 产品与身体的交互方式?(用手按压 vs 用体重压 vs 穿戴 vs 涂抹)
|
|
42
|
+
- 使用场景在哪?(健身房/办公室/家里/户外)
|
|
43
|
+
- 如果用户提供了商品链接,用 WebFetch 抓取产品详情页补充理解
|
|
44
|
+
|
|
45
|
+
3. **展示分析结果**,让用户确认或补充信息。分析结果中必须包含一条明确的「**使用方式描述**」,例如:
|
|
46
|
+
> 使用方式:将花生球放在地面/瑜伽垫上,用户躺在球上方,通过自身体重施压按摩脊柱两侧肌肉。花生形凹槽避开脊柱,两侧球体作用于竖脊肌。
|
|
47
|
+
|
|
48
|
+
### Phase 2: 15 秒脚本 + Prompt 生成
|
|
49
|
+
|
|
50
|
+
基于分析结果 + 参考指南,生成完整的 15 秒视频脚本。
|
|
51
|
+
|
|
52
|
+
**必须参考以下指南**(先 Read 再生成):
|
|
53
|
+
- `${CLAUDE_SKILL_DIR}/references/ecom-prompt-guide.md` — 电商视频 prompt 指南
|
|
54
|
+
|
|
55
|
+
**Prompt 结构(3 个必需组成部分):**
|
|
56
|
+
|
|
57
|
+
#### Part A: 产品锚定(Prompt 开头,一句话)
|
|
58
|
+
|
|
59
|
+
产品外观靠参考图传达,prompt 里只需**一句话**说明产品是什么 + 用途:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
The product is a [brand] [product type] for [primary use case], shown in the reference image.
|
|
63
|
+
The product must match the reference image exactly in every frame. Do not invent any packaging, box, or container unless the reference image shows one.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**关键**:不要在 prompt 里重复描述颜色、材质、形状、logo — 这些信息已在参考图里。把 prompt 空间留给 hook 和画面叙事。
|
|
67
|
+
|
|
68
|
+
#### Part B: 台词嵌入(贯穿全段)
|
|
69
|
+
|
|
70
|
+
台词必须是英文,以强制口型同步格式嵌入叙事段落中:
|
|
71
|
+
```
|
|
72
|
+
Spoken dialogue (say EXACTLY, word-for-word): "..."
|
|
73
|
+
Mouth clearly visible when speaking, lip-sync aligned.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**台词风格要求**:
|
|
77
|
+
- **闺蜜聊天感**:像在跟朋友推荐,不像在念广告词
|
|
78
|
+
- **高信息密度**:每句话都带具体信息(数字、对比、使用场景),没有废话
|
|
79
|
+
- **不硬推销**:结尾不用 "link below" / "点击链接" 这种生硬 CTA,用自然的个人推荐收尾(如 "Best money I have spent this year"、"Trust me just start")
|
|
80
|
+
|
|
81
|
+
**台词节奏**(4 句,对应 4 个时间段):
|
|
82
|
+
```
|
|
83
|
+
[0-3s] Hook — 一句话喊停用户(痛点/悬念/结果前置)
|
|
84
|
+
[3-8s] 卖点 — 具体参数 + 使用体验
|
|
85
|
+
[8-12s] 场景 — 在哪用 + 便携性/多功能
|
|
86
|
+
[12-15s] 收尾 — 个人真实推荐感,不硬推销
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Part C: 画面叙事(一段连续叙事)
|
|
90
|
+
|
|
91
|
+
**视频结构(一个连续 15 秒视频):**
|
|
92
|
+
```
|
|
93
|
+
[0-3s] HOOK — 高冲击力开场。必须:快速运镜(whip pan / snap dolly in)+ 动态动作 + 立即开口说台词。绝对不能慢热。
|
|
94
|
+
[3-8s] SHOWCASE — 产品展示 + 模特互动。运镜变化展示材质细节。
|
|
95
|
+
[8-12s] SCENE — 生活场景使用。拉远到中景/全景。
|
|
96
|
+
[12-15s] CLOSE — 模特面对镜头 + 产品在画面中 + 自然收尾。frame holds steady。
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**输出 3 项内容:**
|
|
100
|
+
|
|
101
|
+
#### 1. Video Prompt(英文,含台词)
|
|
102
|
+
导演口述式段落(6-10 句,每句只做一件事),包含:
|
|
103
|
+
- 产品锚定(一句话,Part A)在最开头
|
|
104
|
+
- 台词以 `Spoken dialogue (say EXACTLY, word-for-word):` 格式嵌入(Part B)
|
|
105
|
+
- 每句台词后跟 `Mouth clearly visible when speaking, lip-sync aligned.`
|
|
106
|
+
- Ad-6D Protocol 元素穿插
|
|
107
|
+
- 模特外观一致性描述(性别、发型、肤色、体型、服装)
|
|
108
|
+
- 运镜变化至少 3 次
|
|
109
|
+
- 光线/氛围描述
|
|
110
|
+
|
|
111
|
+
#### 2. 台词脚本(英文,标注时间段)
|
|
112
|
+
单独列出 4 句台词及对应时间段,方便审阅。
|
|
113
|
+
|
|
114
|
+
#### 3. BGM/音效建议
|
|
115
|
+
- 推荐适合产品调性的音乐风格
|
|
116
|
+
- 关键节点的音效提示
|
|
117
|
+
|
|
118
|
+
**参考示例**:Read `${CLAUDE_SKILL_DIR}/examples/dress-demo.md` 了解最新标准输出格式。
|
|
119
|
+
|
|
120
|
+
### Phase 3: 用户确认
|
|
121
|
+
|
|
122
|
+
展示完整脚本后,询问用户:
|
|
123
|
+
- 是否调整台词
|
|
124
|
+
- 是否更换场景
|
|
125
|
+
- 是否修改 prompt 细节
|
|
126
|
+
- 确认后进入提交
|
|
127
|
+
|
|
128
|
+
### Phase 4: 上传素材 + 提交视频生成任务
|
|
129
|
+
|
|
130
|
+
用户确认脚本后,上传商品图并提交视频生成任务。
|
|
131
|
+
|
|
132
|
+
**重要规则**:
|
|
133
|
+
- 只上传商品图,**不上传模特/真人图**(隐私检测会拦截含真人面孔的图片,报错 `InputImageSensitiveContentDetected.PrivacyInformation`)
|
|
134
|
+
- 模特外观完全靠 prompt 文字描述控制
|
|
135
|
+
- 商品图最好用干净白底纯产品图,避免有营销文字覆盖的图
|
|
136
|
+
- 批量生成时:商品图只需上传一次,复用 material ID 提交多个不同场景的任务
|
|
137
|
+
|
|
138
|
+
## Important Notes
|
|
139
|
+
|
|
140
|
+
- 图片支持 jpg/jpeg/png/webp 格式
|
|
141
|
+
- 视频 prompt 必须全英文
|
|
142
|
+
- 台词必须英文,嵌入 prompt(`Spoken dialogue (say EXACTLY, word-for-word): "..."`)
|
|
143
|
+
- **不输出单独的字幕文案** — 台词已在 prompt 中,不需要额外字幕层
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 完整示例:Keep 弹力阻力带 15 秒带货视频
|
|
2
|
+
|
|
3
|
+
## 输入
|
|
4
|
+
|
|
5
|
+
- 商品图:Keep 品牌弹力阻力带,3 条装(粉/蓝/绿),马卡龙配色
|
|
6
|
+
- 模特参考:运动风女性,金发马尾,运动内衣+紧身短裤(仅供分析,不上传 Renoise)
|
|
7
|
+
|
|
8
|
+
## 商品分析结果
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"product": {
|
|
13
|
+
"type": "弹力阻力带 / resistance loop bands",
|
|
14
|
+
"color": "粉色 10lb, 蓝色 15lb, 薄荷绿 20lb",
|
|
15
|
+
"material": "TPE 弹性材质,哑光质感,柔软亲肤",
|
|
16
|
+
"highlights": "三条不同阻力渐进训练,可折叠便携,马卡龙高颜值配色",
|
|
17
|
+
"brand_tone": "年轻运动,时尚健身"
|
|
18
|
+
},
|
|
19
|
+
"model": {
|
|
20
|
+
"gender": "female",
|
|
21
|
+
"age_range": "25-30",
|
|
22
|
+
"hair": "金发高马尾",
|
|
23
|
+
"outfit": "黑色运动内衣 + 黑色紧身短裤",
|
|
24
|
+
"vibe": "自信、活力、专业健身感"
|
|
25
|
+
},
|
|
26
|
+
"scene_suggestions": [
|
|
27
|
+
"明亮现代客厅晨练",
|
|
28
|
+
"酒店房间旅行健身",
|
|
29
|
+
"卧室睡前拉伸"
|
|
30
|
+
],
|
|
31
|
+
"selling_points": [
|
|
32
|
+
"三条不同阻力,渐进式训练,适合入门到进阶",
|
|
33
|
+
"小巧便携,可折叠放包里随时随地练",
|
|
34
|
+
"马卡龙色系高颜值,不卷边"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 生成脚本
|
|
40
|
+
|
|
41
|
+
### 1. Video Prompt(英文,含台词)
|
|
42
|
+
|
|
43
|
+
> The product is a set of three Keep brand elastic resistance loop bands — flat, wide, smooth matte TPE material with a soft rubbery texture, each band approximately 5cm wide and forming a closed loop. Colors: pastel pink (lightest resistance), sky blue (medium), mint green (heaviest). Each band has a small white "Keep" logo printed on the surface. The bands must match the reference image exactly in color, width, shape, material finish, and logo placement throughout every frame of the video. A fit young woman in her mid-twenties with blonde hair in a high ponytail, light tan skin, athletic build, wearing a black sports bra and black fitted shorts, holds the three pastel-colored Keep resistance bands fanned out in her hand — camera starts extreme close-up on the bands showing their flat wide shape and matte surface then whip pans up to her face as she says "Stop scrolling — I threw out all my gym equipment for these three bands." Morning sunlight from a large window catches the smooth TPE finish. Camera does a fast snap dolly in on her hands as she stretches the blue band taut, the flat wide band maintaining its shape and thickness as it stretches, she says "Ten, fifteen, twenty pounds — I started pink, now I am on green, and they never roll up on you." She has the mint green band already looped around both ankles, camera pulls back to medium shot as she performs side leg raises, the wide flat band visible around her ankles keeping its shape, she says "I do legs in my living room, arms on work trips — they fold smaller than my phone" while transitioning into a squat pulse with the pink band above her knees. Without stopping she grabs all three bands, folds them into a tiny square and tucks them into a small gym bag pocket, camera pushes in tight, then she looks straight into the camera with a knowing grin and says "Honestly the best forty bucks I have spent this year," the pastel colors pop against her black outfit, warm golden backlight creates a soft halo, frame holds steady.
|
|
44
|
+
|
|
45
|
+
### 2. 台词脚本(英文)
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
[0-3s] "Stop scrolling — I threw out all my gym equipment for these three bands."
|
|
49
|
+
[3-8s] "Ten, fifteen, twenty pounds — I started pink, now I'm on green, and they never roll up on you."
|
|
50
|
+
[8-12s] "I do legs in my living room, arms on work trips — they fold smaller than my phone."
|
|
51
|
+
[12-15s] "Honestly the best forty bucks I've spent this year."
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 3. BGM/音效建议
|
|
55
|
+
|
|
56
|
+
- **BGM**:高能量 trap-pop beat,BPM 125-135,bass drop 配合 0s hook
|
|
57
|
+
- **音效**:
|
|
58
|
+
- [0s] 弹力带 snap 回弹声 — 配合开场冲击
|
|
59
|
+
- [3s] 快速 whoosh 转场音
|
|
60
|
+
- [8s] 运动节奏鼓点加重
|
|
61
|
+
- [12s] bass swell + 定格 hit
|
|
62
|
+
|
|
63
|
+
## Renoise 提交
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 1. 上传商品图(只传商品图,不传模特图)
|
|
67
|
+
node renoise-cli.mjs material upload <商品图路径>
|
|
68
|
+
# → 返回 material id,例如 194
|
|
69
|
+
|
|
70
|
+
# 2. 提交任务(带商品图 material,一步到位)
|
|
71
|
+
node renoise-cli.mjs task generate \
|
|
72
|
+
--prompt "<上面的 Video Prompt>" \
|
|
73
|
+
--model renoise-2.0 --duration 15 --ratio 9:16 \
|
|
74
|
+
--tags ecom,keep,resistance-band \
|
|
75
|
+
--materials "194:image1"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 多场景批量生成
|
|
79
|
+
|
|
80
|
+
同一商品可复用 material ID,换不同场景生成多个视频:
|
|
81
|
+
|
|
82
|
+
| 场景 | Hook 台词 | 场景关键词 |
|
|
83
|
+
|------|----------|-----------|
|
|
84
|
+
| 户外公园晨练 | "This tiny thing replaced my entire gym bag." | sunlit park lawn, golden hour, dewy grass |
|
|
85
|
+
| 酒店旅行健身 | "Business trip day three and I still have not skipped a workout." | hotel room, city skyline, suitcase |
|
|
86
|
+
| 卧室睡前拉伸 | "My nighttime routine that actually changed my body." | cozy bedroom, string lights, yoga mat |
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# 电商短视频 Prompt 指南
|
|
2
|
+
|
|
3
|
+
## 15 秒电商视频 Prompt 模板
|
|
4
|
+
|
|
5
|
+
### 核心结构:一个连续 15 秒叙事段落
|
|
6
|
+
|
|
7
|
+
不同于 Apple Don't Blink 快速切镜风格,电商带货视频是**一个连续镜头**,通过运镜变化展示产品和模特。
|
|
8
|
+
|
|
9
|
+
**写作顺序**: 时间线叙事 + Ad-6D 元素穿插
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
[开场 0-3s] ⚡ HOOK — 产品必须在第 1 秒出现 + 快速运镜 + 立即开口说话。绝对不能铺垫。
|
|
13
|
+
[展示 3-8s] 产品特写 + 材质细节 + 模特互动
|
|
14
|
+
[场景 8-12s] 生活场景 + 使用效果 + 氛围
|
|
15
|
+
[收尾 12-15s] 模特面对镜头 + 产品定格 + 自然收尾
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 产品锚定(Prompt 开头,一句话)
|
|
19
|
+
|
|
20
|
+
产品外观靠参考图传达,prompt 里只需**一句话**说明产品是什么 + 用途:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
The product is a [brand] [product type] for [primary use case], shown in the reference image.
|
|
24
|
+
The product must match the reference image exactly in every frame. Do not invent any packaging, box, or container unless the reference image shows one.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**示例**:
|
|
28
|
+
- `The product is a K brand lightweight gym tote bag for fitness and daily commute, shown in the reference image.`
|
|
29
|
+
- `The product is a Keep peanut-shaped massage ball for back and muscle recovery, shown in the reference image.`
|
|
30
|
+
|
|
31
|
+
**关键**:不要在 prompt 里重复描述产品的颜色、材质、形状、logo — 这些信息已经在参考图里了。把 prompt 空间留给 hook 和画面叙事。
|
|
32
|
+
|
|
33
|
+
### 模特一致性描述
|
|
34
|
+
|
|
35
|
+
紧接产品锚定段之后,锚定模特外观:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
A [age_range]-year-old [gender] with [hair description], [skin tone], [body type], wearing [outfit description]...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**注意**:模特完全靠文字描述,不上传真人参考图(隐私检测会拦截含真人面孔的图片)。
|
|
42
|
+
|
|
43
|
+
## 品类专用关键词
|
|
44
|
+
|
|
45
|
+
### 服装(Clothing)
|
|
46
|
+
- **面料**: flowing silk, crisp cotton, soft cashmere, stretchy knit, lightweight chiffon, structured tweed
|
|
47
|
+
- **动态**: fabric sways gently, hem flutters in breeze, pleats catch light, drape follows body movement
|
|
48
|
+
- **展示**: twirls to show full skirt volume, adjusts collar detail, runs fingers along seam
|
|
49
|
+
- **场景**: sunlit café terrace, cherry blossom garden path, minimalist white studio, golden hour rooftop
|
|
50
|
+
|
|
51
|
+
### 3C 数码(Electronics)
|
|
52
|
+
- **材质**: anodized aluminum, gorilla glass surface, matte finish, chamfered edges catch light
|
|
53
|
+
- **动态**: screen illuminates face, finger glides across display, device rotates to reveal thin profile
|
|
54
|
+
- **展示**: holds up to camera showing screen, taps interface with precision, places on wireless charger
|
|
55
|
+
- **场景**: modern desk setup, coffee shop workspace, commuter holding device, bedside nightstand
|
|
56
|
+
|
|
57
|
+
### 美妆(Beauty)
|
|
58
|
+
- **质感**: dewy finish, velvety matte, glossy sheen, shimmering particles, creamy texture
|
|
59
|
+
- **动态**: applies with brush stroke, blends with fingertip, lips press together, eyelids flutter
|
|
60
|
+
- **展示**: close-up of application, before-after glow, product swatch on skin, mirror reflection
|
|
61
|
+
- **场景**: vanity mirror with ring light, bathroom morning routine, getting ready for night out
|
|
62
|
+
|
|
63
|
+
### 食品(Food)
|
|
64
|
+
- **质感**: steam rises, sauce glistens, crispy golden crust, juice drips, cheese stretches
|
|
65
|
+
- **动态**: pours into bowl, breaks apart to reveal filling, scoops with spoon, bites with satisfaction
|
|
66
|
+
- **展示**: overhead flat lay, cross-section reveal, slow-motion pour, garnish placement
|
|
67
|
+
- **场景**: rustic kitchen counter, outdoor picnic, cozy dining table, street food stall
|
|
68
|
+
|
|
69
|
+
### 家居(Home)
|
|
70
|
+
- **材质**: warm wood grain, soft linen texture, smooth ceramic, brushed brass hardware
|
|
71
|
+
- **动态**: hand caresses surface, opens drawer smoothly, arranges on shelf, light shifts across surface
|
|
72
|
+
- **展示**: styled vignette, before-after room transformation, detail close-up, scale with hand
|
|
73
|
+
- **场景**: morning light through curtains, minimalist living room, cozy bedroom corner, modern kitchen
|
|
74
|
+
|
|
75
|
+
## 模特与产品互动动作词汇表
|
|
76
|
+
|
|
77
|
+
### 通用动作
|
|
78
|
+
- **展示**: holds up to camera, presents with both hands, turns to show different angle
|
|
79
|
+
- **触摸**: runs fingers along, gently touches, traces the outline of
|
|
80
|
+
- **穿戴**: puts on, adjusts, styles with
|
|
81
|
+
- **使用**: opens, activates, applies
|
|
82
|
+
- **情感**: smiles confidently, looks surprised, nods approvingly, expresses delight
|
|
83
|
+
|
|
84
|
+
### 服装专用
|
|
85
|
+
- twirls gracefully, walks toward camera, poses with hand on hip, flips hair to show neckline, adjusts sleeve cuff, smooths fabric over hip, turns to reveal back detail
|
|
86
|
+
|
|
87
|
+
### 3C 专用
|
|
88
|
+
- unboxes with anticipation, swipes through interface, holds up comparing to face size, places in pocket to show portability, tilts to catch light on screen
|
|
89
|
+
|
|
90
|
+
### 美妆专用
|
|
91
|
+
- applies with practiced motion, checks reflection, touches cheek feeling texture, pouts showing lip color, blinks showing eye makeup
|
|
92
|
+
|
|
93
|
+
## 台词写作规范
|
|
94
|
+
|
|
95
|
+
**核心原则**:台词必须是英文,嵌入视频 prompt 中。不单独输出字幕。
|
|
96
|
+
|
|
97
|
+
**嵌入格式**(强制口型同步):
|
|
98
|
+
```
|
|
99
|
+
Spoken dialogue (say EXACTLY, word-for-word): "..."
|
|
100
|
+
Mouth clearly visible when speaking, lip-sync aligned.
|
|
101
|
+
```
|
|
102
|
+
使用 `Spoken dialogue (say EXACTLY, word-for-word):` 而不是简单的 `says "..."`,可以显著提升口型同步精度。每句台词后跟 `Mouth clearly visible when speaking, lip-sync aligned.` 确保嘴部可见。
|
|
103
|
+
|
|
104
|
+
**风格**:闺蜜聊天感 — 像在跟朋友推荐,不像在念广告词。每句话都带具体信息(数字、对比、使用场景),没有废话。
|
|
105
|
+
|
|
106
|
+
### Hook 台词(0-3s)— 第一句话喊停用户
|
|
107
|
+
|
|
108
|
+
**颠覆型**(最有效):
|
|
109
|
+
- "Stop scrolling — I threw out all my gym equipment for these three bands."
|
|
110
|
+
- "This tiny thing replaced my entire gym bag."
|
|
111
|
+
- "Business trip day three and I still have not skipped a workout."
|
|
112
|
+
|
|
113
|
+
**个人经历型**:
|
|
114
|
+
- "My nighttime routine that actually changed my body."
|
|
115
|
+
- "The one thing I have been recommending to literally everyone."
|
|
116
|
+
|
|
117
|
+
**关键**:开口必须快,配合快速运镜(whip pan / snap dolly in),不能慢热。
|
|
118
|
+
|
|
119
|
+
### 卖点台词(3-8s)— 具体参数 + 使用体验
|
|
120
|
+
|
|
121
|
+
- "Ten, fifteen, twenty pounds — I started pink, now I am on green, and they never roll up on you."
|
|
122
|
+
- "Three resistance levels, folds flat, weighs literally nothing — this is my entire travel gym."
|
|
123
|
+
- 必须包含:具体数字 + 个人使用感受 + 差异化优势
|
|
124
|
+
|
|
125
|
+
### 场景台词(8-12s)— 在哪用 + 便携/多功能
|
|
126
|
+
|
|
127
|
+
- "I do legs in my living room, arms on work trips — they fold smaller than my phone."
|
|
128
|
+
- "Park, backyard, hotel balcony — I have zero excuses now."
|
|
129
|
+
- 必须包含:至少 2 个使用场景 + 便携性/多功能性
|
|
130
|
+
|
|
131
|
+
### 收尾台词(12-15s)— 自然个人推荐,不硬推销
|
|
132
|
+
|
|
133
|
+
**好的收尾**(推荐):
|
|
134
|
+
- "Honestly the best forty bucks I have spent this year."
|
|
135
|
+
- "Trust me just start — future you will be so grateful."
|
|
136
|
+
- "Best thing I ever packed."
|
|
137
|
+
- "You are welcome."
|
|
138
|
+
|
|
139
|
+
**避免的收尾**(太生硬):
|
|
140
|
+
- ~~"Link below — grab yours before they sell out."~~
|
|
141
|
+
- ~~"Click the link for a special discount."~~
|
|
142
|
+
- ~~"库存不多了,想要的赶紧!"~~
|
|
143
|
+
|
|
144
|
+
## Hook 策略(前 3 秒生死线)
|
|
145
|
+
|
|
146
|
+
**数据**:63% 高 CTR 的 TikTok 视频在前 3 秒就抓住用户。用户做出"看 or 划走"决策只需 **1.7 秒**。3 秒留存率 65%+ 的视频获得 **4-7 倍**曝光。
|
|
147
|
+
|
|
148
|
+
### 视觉 Hook 技巧(选一个用于 prompt 开头)
|
|
149
|
+
|
|
150
|
+
| 技巧 | Prompt 写法 | 效果 |
|
|
151
|
+
|------|-------------|------|
|
|
152
|
+
| **极速 zoom-in** | `Camera snaps in extreme close-up on the [product]` | 产品第 1 帧出现,冲击力最强 |
|
|
153
|
+
| **产品滑入画面** | `The [product] slides into frame from the right` | 突然出现,制造微悬念 |
|
|
154
|
+
| **手持举起** | `A hand thrusts the [product] toward the camera` | 直接、UGC 感强 |
|
|
155
|
+
| **特写→全景反转** | `Extreme macro on [texture detail], camera rapidly pulls back to reveal...` | 先抓细节好奇,再揭示全貌 |
|
|
156
|
+
| **Whip pan 甩入** | `Camera whip-pans with motion blur and lands on the [product]` | 节奏感强,视觉冲击 |
|
|
157
|
+
|
|
158
|
+
### Hook 核心规则
|
|
159
|
+
|
|
160
|
+
1. **产品必须在第 1 秒出现** — 不能先拍人走路、开门、铺环境
|
|
161
|
+
2. **第 1 秒必须有运动** — 静止开场 = 被划走
|
|
162
|
+
3. **模特必须在前 2 秒开口说话** — 声音比画面更能留人
|
|
163
|
+
4. **Hook 台词要像在喊停朋友** — 不是念广告词
|
|
164
|
+
|
|
165
|
+
### Hook 台词公式(按效果排序)
|
|
166
|
+
|
|
167
|
+
1. **结果前置**: "This $30 bag replaced my gym bag AND my purse." — 直接展示结果
|
|
168
|
+
2. **颠覆型**: "Stop carrying two bags to the gym — you only need this one." — 挑战现有习惯
|
|
169
|
+
3. **社交证明**: "200K people bought this last month and I finally get why." — FOMO
|
|
170
|
+
4. **痛点提问**: "Why is your gym bag always so heavy?" — 直击痛点
|
|
171
|
+
5. **个人故事**: "I was that person with three bags until I found this." — 共鸣
|
|
172
|
+
|
|
173
|
+
## 运镜节奏建议(15 秒连续镜头)
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
[0-3s] HOOK — 产品第 1 帧出现!极速运镜 + 立即开口
|
|
177
|
+
推荐:extreme close-up snap in / whip pan / product slides into frame
|
|
178
|
+
禁止:camera slowly pushes in, 人物走路铺垫, 空镜头开场
|
|
179
|
+
节奏:1-2 秒内完成第一个运镜变化
|
|
180
|
+
|
|
181
|
+
[3-8s] SHOWCASE — 特写 → 中景切换,展示产品细节
|
|
182
|
+
推荐:fast snap dolly in on details,
|
|
183
|
+
camera orbits or slides to reveal texture
|
|
184
|
+
|
|
185
|
+
[8-12s] SCENE — 拉远到中景/全景,展示使用场景
|
|
186
|
+
推荐:camera pulls back to reveal full scene,
|
|
187
|
+
natural movement as model interacts with environment
|
|
188
|
+
|
|
189
|
+
[12-15s] CLOSE — 回到中景,面对镜头,定格
|
|
190
|
+
推荐:camera pushes in tight, then settles,
|
|
191
|
+
model faces camera, product in frame,
|
|
192
|
+
frame holds steady(最后这个定格很重要)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## BGM 音乐指令(Prompt 内指定)
|
|
196
|
+
|
|
197
|
+
视频模型可以在视频中生成背景音乐。**必须在 prompt 末尾加上 BGM 指令**:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
Background music: [genre/mood description], [tempo], [energy level].
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**BGM 选择指南**:
|
|
204
|
+
|
|
205
|
+
| 商品类型 | 推荐 BGM | Prompt 写法 |
|
|
206
|
+
|----------|----------|-------------|
|
|
207
|
+
| 运动/健身 | 节奏感强的电子/lo-fi | `Background music: upbeat electronic lo-fi beat, medium-fast tempo, energetic and motivating.` |
|
|
208
|
+
| 美妆/护肤 | 温暖 R&B / chill pop | `Background music: warm chill R&B, slow-medium tempo, soft and intimate.` |
|
|
209
|
+
| 3C 数码 | 干净 minimal / tech | `Background music: clean minimal electronic, medium tempo, modern and sleek.` |
|
|
210
|
+
| 时尚服装 | Indie pop / trendy | `Background music: trendy indie pop, medium tempo, stylish and confident.` |
|
|
211
|
+
| 家居 | Acoustic / ambient | `Background music: warm acoustic guitar, slow tempo, cozy and relaxing.` |
|
|
212
|
+
| 食品 | Jazz / feel-good | `Background music: feel-good jazz, medium tempo, cheerful and appetizing.` |
|
|
213
|
+
|
|
214
|
+
**关键**:BGM 要配合视频节奏 — Hook 段需要能量感,收尾段可以稍缓。音乐风格要匹配产品调性。
|
|
215
|
+
|
|
216
|
+
## Prompt 写作风格:导演口述式(Director Dictation)
|
|
217
|
+
|
|
218
|
+
Prompt 应写成导演在片场口述指令的风格 — 6-10 句英文,每句只做一件事。避免把多个动作堆在一句长句里。
|
|
219
|
+
|
|
220
|
+
**好的写法**(每句一个动作/镜头指令):
|
|
221
|
+
```
|
|
222
|
+
Camera snaps in on a close-up of the pink peanut massage ball sitting on a yoga mat.
|
|
223
|
+
A 25-year-old woman with a high ponytail and black leggings walks into frame.
|
|
224
|
+
She picks up the ball and holds it up to the camera.
|
|
225
|
+
Spoken dialogue (say EXACTLY, word-for-word): "This little thing saved my back after deadlifts."
|
|
226
|
+
Mouth clearly visible when speaking, lip-sync aligned.
|
|
227
|
+
She places the ball on the mat and lies down on it, rolling her spine.
|
|
228
|
+
Camera pulls back to a medium shot showing the full living room scene.
|
|
229
|
+
...
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**不好的写法**(一句话塞太多动作):
|
|
233
|
+
```
|
|
234
|
+
A woman enters carrying a pink ball while the camera pans and she says "..." as she lies down and rolls.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Prompt 质量检查清单
|
|
238
|
+
|
|
239
|
+
- [ ] 纯英文导演口述式段落(6-10 句,每句一件事)
|
|
240
|
+
- [ ] **开头有产品锚定**(一句话:产品是什么 + 用途 + 匹配参考图 + 无包装锁)
|
|
241
|
+
- [ ] 紧接有模特外观锚定描述
|
|
242
|
+
- [ ] **台词用 `Spoken dialogue (say EXACTLY, word-for-word):` 格式**(英文,4 句,闺蜜聊天感)
|
|
243
|
+
- [ ] 每句台词后跟 `Mouth clearly visible when speaking, lip-sync aligned.`
|
|
244
|
+
- [ ] Hook 台词在第一句,配合快速运镜
|
|
245
|
+
- [ ] 收尾台词自然不硬推销
|
|
246
|
+
- [ ] 包含具体的产品材质描述词
|
|
247
|
+
- [ ] 运镜变化至少 3 次
|
|
248
|
+
- [ ] 包含光线/氛围描述
|
|
249
|
+
- [ ] 模特与产品有明确互动
|
|
250
|
+
- [ ] 结尾 frame holds steady
|
|
251
|
+
- [ ] 整体节奏:快开 → 细展 → 场景 → 定格
|
|
252
|
+
- [ ] **末尾有 BGM 指令**(`Background music: [genre], [tempo], [energy]`)
|
|
253
|
+
- [ ] Hook 段产品在第 1 帧出现,不铺垫
|
|
254
|
+
|
|
255
|
+
## Renoise 提交注意事项
|
|
256
|
+
|
|
257
|
+
- **必须上传商品图**作为 material(image1),产品还原度显著提升
|
|
258
|
+
- **不上传真人模特图**,隐私检测会拦截(报错 PrivacyInformation)
|
|
259
|
+
- 模特外观完全靠 prompt 文字描述控制
|
|
260
|
+
- 商品图最好用干净白底纯产品图,避免有营销文字覆盖的图
|
|
261
|
+
- 批量生成时复用同一 material ID,换场景/台词即可
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Analyze product + model images using Gemini for ecommerce video scripting.
|
|
4
|
+
* Usage: npx tsx analyze-images.ts <product_image> [model_image]
|
|
5
|
+
* Model image is optional — if omitted, only product analysis is returned.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs/promises'
|
|
9
|
+
import path from 'path'
|
|
10
|
+
import { getGeminiClient, fileToInlinePart } from '../../../lib/gemini.js'
|
|
11
|
+
|
|
12
|
+
const PROMPT_WITH_MODEL = `You are an expert ecommerce video director and product analyst. Analyze these two images:
|
|
13
|
+
|
|
14
|
+
Image 1: Product photo
|
|
15
|
+
Image 2: Model/person photo
|
|
16
|
+
|
|
17
|
+
Return a JSON object with exactly this structure (no markdown, no code fences, pure JSON only):
|
|
18
|
+
|
|
19
|
+
{
|
|
20
|
+
"product": {
|
|
21
|
+
"type": "product category (e.g. dress, sneaker, lipstick)",
|
|
22
|
+
"color": "main colors",
|
|
23
|
+
"material": "fabric/material description",
|
|
24
|
+
"highlights": "key visual features and design details",
|
|
25
|
+
"brand_tone": "brand positioning vibe (e.g. luxury, streetwear, minimalist)"
|
|
26
|
+
},
|
|
27
|
+
"model": {
|
|
28
|
+
"gender": "male/female",
|
|
29
|
+
"age_range": "estimated age range",
|
|
30
|
+
"hair": "hair style and color description",
|
|
31
|
+
"outfit": "what the model is wearing",
|
|
32
|
+
"vibe": "overall style/aesthetic (e.g. elegant, sporty, casual chic)"
|
|
33
|
+
},
|
|
34
|
+
"scene_suggestions": [
|
|
35
|
+
"scene 1 description with specific location and lighting",
|
|
36
|
+
"scene 2 description with specific location and lighting",
|
|
37
|
+
"scene 3 description with specific location and lighting"
|
|
38
|
+
],
|
|
39
|
+
"selling_points": [
|
|
40
|
+
"selling point 1 — specific and compelling",
|
|
41
|
+
"selling point 2 — specific and compelling",
|
|
42
|
+
"selling point 3 — specific and compelling"
|
|
43
|
+
]
|
|
44
|
+
}`
|
|
45
|
+
|
|
46
|
+
const PROMPT_PRODUCT_ONLY = `You are an expert ecommerce video director and product analyst. Analyze this product image.
|
|
47
|
+
|
|
48
|
+
Return a JSON object with exactly this structure (no markdown, no code fences, pure JSON only):
|
|
49
|
+
|
|
50
|
+
{
|
|
51
|
+
"product": {
|
|
52
|
+
"type": "product category (e.g. dress, sneaker, lipstick)",
|
|
53
|
+
"color": "main colors",
|
|
54
|
+
"material": "fabric/material description",
|
|
55
|
+
"highlights": "key visual features and design details",
|
|
56
|
+
"brand_tone": "brand positioning vibe (e.g. luxury, streetwear, minimalist)"
|
|
57
|
+
},
|
|
58
|
+
"scene_suggestions": [
|
|
59
|
+
"scene 1 description with specific location and lighting",
|
|
60
|
+
"scene 2 description with specific location and lighting",
|
|
61
|
+
"scene 3 description with specific location and lighting"
|
|
62
|
+
],
|
|
63
|
+
"selling_points": [
|
|
64
|
+
"selling point 1 — specific and compelling",
|
|
65
|
+
"selling point 2 — specific and compelling",
|
|
66
|
+
"selling point 3 — specific and compelling"
|
|
67
|
+
]
|
|
68
|
+
}`
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const [productImage, modelImage] = process.argv.slice(2)
|
|
72
|
+
if (!productImage) {
|
|
73
|
+
console.error('Usage: analyze-images.ts <product_image> [model_image]')
|
|
74
|
+
process.exit(1)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Validate files exist
|
|
78
|
+
await fs.access(productImage).catch(() => {
|
|
79
|
+
console.error(`ERROR: Product image not found: ${productImage}`)
|
|
80
|
+
process.exit(1)
|
|
81
|
+
})
|
|
82
|
+
if (modelImage) {
|
|
83
|
+
await fs.access(modelImage).catch(() => {
|
|
84
|
+
console.error(`ERROR: Model image not found: ${modelImage}`)
|
|
85
|
+
process.exit(1)
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const genAI = getGeminiClient()
|
|
90
|
+
const model = genAI.getGenerativeModel({
|
|
91
|
+
model: process.env.GEMINI_MODEL ?? 'gemini-3.1-flash',
|
|
92
|
+
generationConfig: {
|
|
93
|
+
temperature: 0.3,
|
|
94
|
+
maxOutputTokens: 2048,
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const productPart = await fileToInlinePart(productImage)
|
|
99
|
+
|
|
100
|
+
const parts: Array<{ text: string } | Awaited<ReturnType<typeof fileToInlinePart>>> = modelImage
|
|
101
|
+
? [{ text: PROMPT_WITH_MODEL }, productPart, await fileToInlinePart(modelImage)]
|
|
102
|
+
: [{ text: PROMPT_PRODUCT_ONLY }, productPart]
|
|
103
|
+
|
|
104
|
+
const result = await model.generateContent(parts)
|
|
105
|
+
|
|
106
|
+
const text = result.response.text()
|
|
107
|
+
|
|
108
|
+
// Try to parse and pretty-print as JSON
|
|
109
|
+
const cleaned = text.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim()
|
|
110
|
+
try {
|
|
111
|
+
const parsed = JSON.parse(cleaned)
|
|
112
|
+
console.log(JSON.stringify(parsed, null, 2))
|
|
113
|
+
} catch {
|
|
114
|
+
// If not valid JSON, output raw text
|
|
115
|
+
console.log(text)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
main().catch((err) => {
|
|
120
|
+
console.error('ERROR:', err.message)
|
|
121
|
+
process.exit(1)
|
|
122
|
+
})
|