Clone ad — Seedance 2.0
Clone an existing video ad for a different product or offer. The agent analyzes the
source video frame-by-frame, transcribes dialogue, extracts the visual style and
beat structure, then generates a new Seedance 2.0 video adapted for the user's product.
How this differs from analyze-video:
- analyze-video → output is a reusable markdown template saved to
prompt-library/
- clone-ad → output is a generated Seedance 2.0 video delivered to the user
Prerequisites
Before starting, verify:
which ffmpeg || echo "MISSING — run: brew install ffmpeg"
python3 -c "import whisper; print('whisper OK')" 2>/dev/null || echo "MISSING — run: pip3 install openai-whisper"
Both extract-frames.sh and whisper depend on ffmpeg. If missing, install via brew install ffmpeg before proceeding.
Workflow
Step 0: Gather inputs
Collect from the user:
| Input |
Required |
Notes |
| Source video |
yes |
The video ad to clone. File path to .mp4, .mov, .webm |
| Product image |
recommended |
Reference photo of the user's product. Becomes referenceImages / @(img1) in the prompt. Without this, Seedance invents its own product design. |
| Product/offer description |
if no image |
Text description of the product, its features, target audience, and key selling points. Used to rewrite dialogue and product references. |
| Brand voice |
optional |
Check MASTER_CONTEXT.md for brand blocks. If empty, ask the user for tone/audience preferences. |
If the user only provides a video and says "clone this for my product," ask them for
at least a product image or a text description before proceeding.
Step 1: Extract frames and audio
Reuse the analyze-video extraction script — do NOT duplicate it.
bash "skills/arcads-external-api/prompting/analyze-video/scripts/extract-frames.sh" \
"<source_video_path>" "/tmp/clone-ad-analysis" <num_frames>
Frame count by duration:
| Source duration |
Frames |
| Under 10s |
8 |
| 10–20s |
12 |
| 20–30s |
16 |
| Over 30s |
20 |
Outputs:
frame_001.jpg through frame_NNN.jpg
audio.wav (16 kHz mono, whisper-ready)
metadata.txt (duration, resolution, fps, frame count)
Read metadata.txt to get the source video duration — you'll need it for step 6.
Step 2: Transcribe audio
Use whisper to get the exact dialogue. This is critical — the dialogue pattern is what
gets adapted for the user's product.
import whisper
model = whisper.load_model("base")
result = model.transcribe("/tmp/clone-ad-analysis/audio.wav")
Record:
- Full transcript text
- Per-segment timestamps and text (
result["segments"])
- Total word count
- Language detected
If the video is silent (no speech detected), note that and skip the dialogue
adaptation in step 7. The clone will be a visual-style clone only.
Step 3: Compressed analysis
Read ALL extracted frames visually. For each frame, note:
Structure and pacing:
- How many distinct beats/shots are there?
- What's the narrative arc? (hook → demo → verdict? reveal → detail → CTA?)
- How long does each beat last? (map to segment timestamps)
Camera and framing:
- POV style: selfie/handheld, tripod, propped phone, over-the-shoulder?
- Framing per beat: wide, medium, close-up, macro?
- Camera movement: static, pan, dolly, handheld shake?
- Signature framing moves (e.g., "leans into camera," "tilts product toward lens")
Edit style:
- Transition type: jump cuts, dissolves, match cuts?
- Visual rhythm: fast cuts vs held shots?
- Any recurring motif (e.g., "every other beat is an extreme close-up")?
Dialogue and script structure:
- Hook format: question, statement, exclamation, reaction?
- Speech pattern: casual/formal, filler words, trailing thoughts, mid-sentence cuts?
- How many spoken lines? How many silent beats?
- CTA style: direct ("link in bio"), soft ("you need to try this"), none?
Tone and energy:
- Emotion words that describe the speaker/mood
- Energy arc: starts calm → builds excitement? Flat? Burst then settle?
- Speaker's relationship to viewer: friend, expert, skeptic, fan?
Lighting and technical quality:
- Light source: natural/artificial, direction, quality
- Camera quality: phone/DSLR/cinema, intentional flaws?
- Audio quality: phone mic, studio, car, outdoor?
Product references:
- How is the product physically shown? (held up, worn, applied, on a surface)
- What specific claims or features are called out?
- Brand mentions, labels visible, text overlays?
What makes this ad distinctive (2–3 defining traits):
- The unique combination of elements that makes this ad recognizable
- These are the traits that MUST transfer to the clone
Store this analysis internally — it does NOT get saved as a template file.
Step 4: Present analysis summary
Show the user a structured breakdown before proceeding:
📋 Source video analysis
Duration: Xs | Beats: N | Dialogue: Y words | Style: [style name]
Beat map:
[00:00–00:03] HOOK — close-up, excited expression, "opening line"
[00:03–00:07] SHOW — tilts product to camera, "feature call-out"
[00:07–00:10] DEMO — (silent) applies/uses product, close-up on texture
[00:10–00:15] VERDICT — back to camera, "closing line + CTA"
Defining traits:
1. [trait 1]
2. [trait 2]
3. [trait 3]
What transfers to your product:
✅ Beat structure, pacing, camera angles, edit style, tone, energy
✅ Dialogue pattern (adapted for your product)
✅ Lighting and technical quality cues
What gets swapped:
🔄 Product references → your product
🔄 Specific claims → your product's features
🔄 Brand mentions → your brand (if provided)
Proceed with adaptation? (yes / adjust)
Wait for user confirmation before continuing.
Step 5: Decide generation mode
Walk through this decision tree:
┌─ Source video ≤ 15s?
│ YES → Single-clip generation
│ NO → Multi-clip split at natural beat boundaries
│ Each clip ≤ 15s (Seedance max)
│ Identify best split points from beat map
│ Use the CHAINED MULTI-CLIP PIPELINE below
│
├─ User provided a product IMAGE?
│ YES → Image-to-video mode (referenceImages with @(img1) in prompt)
│ For multi-clip: use i2v for clip 1 ONLY, then chain v2v for clips 2+
│ NO → Text-only mode (describe product in prompt text only)
│ OR v2v if:
│ - Source video has NO human faces
│ - AND user wants to preserve exact visual style
│ - (v2v with faces → content checker rejection + billed)
│
├─ Source video has person SPEAKING?
│ YES → audioEnabled: true (confirm with user)
│ Dialogue confirmation gate REQUIRED (step 7)
│ NO → audioEnabled: false (or ask user preference)
│ Skip dialogue gate
│
└─ User wants voice clone from source audio?
YES → Upload source audio as referenceAudios
(check audio+image regression: run sanity probe first)
NO → Seedance generates its own voice from text
Chained multi-clip pipeline (confirmed 2026-04-10)
When the source ad is longer than 15s, use this hybrid i2v→v2v chaining pattern for visual continuity:
Clip 1: i2v mode
- referenceImages: [product image] ← establishes brand fidelity
- audioEnabled: true (if speech)
- Generate → poll → download output
Clip 2: v2v mode
- referenceVideos: [clip 1 output] ← inherits hands, surface, lighting, product
- NO referenceImages (mutually exclusive)
- audioEnabled: true (if speech)
- Upload clip 1 output via fresh presigned URL
- Generate → poll → download output
Clip 3: v2v mode
- referenceVideos: [clip 2 output] ← chain from MOST RECENT clip, not clip 1
- Upload clip 2 output via fresh presigned URL
- Generate → poll → download output
...continue for clips 4+
Critical rules for chaining:
- Always chain from the most recent clip — do not reuse earlier uploads. Presigned URLs expire and stale uploads may fail silently.
- Upload each clip output fresh via
POST /v1/file-upload/get-presigned-url immediately before using it as a reference. Do not reuse filePath values from previous uploads.
- Wait for each clip to reach
generated status before uploading it as a reference for the next clip. Do not fire clips in parallel — they must be sequential.
- Clip 1 uses i2v for brand fidelity (product image as reference). All subsequent clips use v2v (previous clip as reference) for visual continuity.
- After all clips are generated, stitch with ffmpeg:
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4 (use absolute paths in the list file).
Why chaining works: Seedance v2v inherits the visual style, hands, surface, lighting, and product appearance from the reference video. By chaining clip N → clip N+1, each subsequent clip maintains continuity with the one before it. The first clip's i2v reference image establishes the product identity; v2v propagates it through the series.
Cost note: Clip 1 costs the i2v rate (0.06/sec, 0.9 cr at 15s). Clips 2+ cost the v2v rate (0.1/sec, 1.5 cr at 15s). A 3-clip series costs ~0.9 + 1.5 + 1.5 = ~3.9 credits total.
Important constraints to check:
referenceImages and referenceVideos are mutually exclusive — pick one per call
- v2v with human-containing reference videos → content checker rejection (credits burned)
audioEnabled: true + referenceImages may 500 (intermittent server regression) — sanity probe first
referenceVideos count > 1 fails — only 1 ref video works
- If using v2v: only use product-only/abstract/hands-only videos (no faces)
- Hands-only clips (no face visible) pass the v2v content checker — confirmed 2026-04-10
Tell the user which mode you're using and why.
Step 6: Adapt for user's product
This is the creative core. Using the analysis from step 3:
Dialogue adaptation (if source has speech):
- Keep the same conversational pattern: if the source uses a question hook, use a question hook. If it uses filler words ("like," "okay so"), keep filler words.
- Keep the same number of spoken lines and same silent beat placement
- Keep the same energy arc (excited → calm, or flat, or building)
- Replace product-specific references with the user's product name, features, and claims
- Match the word count of each line closely (±3 words per beat) to preserve pacing
- Read the adapted dialogue out loud at natural pace — it must fit the target duration
Visual adaptation:
- Keep the analyzed camera work, framing per beat, and edit style
- Replace the product description with the user's product (physical appearance, colors, materials, label details)
- Keep the setting, lighting, and atmosphere
- Keep the person description (or adapt if user specifies a different persona)
- Keep the technical flaw cues (phone quality, mic type, lighting imperfections)
Prompt composition:
- Read seedance-2.md for platform rules before composing
- Read the closest matching style template (e.g., seedance-2-ugc.md for UGC-style sources) for structural guidance
- Follow the Subject + Action + Camera + Style + Constraints order
- Stay within 100–260 words (Seedance sweet spot)
- Include
@(img1) token if user provided a product image
- Add consistency anchors: "The product from @(img1) must remain visually unchanged in every shot"
- Add pacing cues in the tone direction paragraph
- Use timestamps
[00:00], [00:04], etc. for multi-beat sequences
- No forbidden words: cinematic, professional, stunning, 8k, studio, perfect
Duration selection:
- If source ≤ 15s: match source duration (or round to nearest second in 4–15 range)
- If source > 15s: split into clips, each ≤ 15s
- Use dialogue word count to validate (see main SKILL.md duration table: ~2.5 words/sec)
Step 7: Dialogue confirmation gate
MANDATORY for any clone with spoken dialogue. Follow the exact format from the
main SKILL.md:
📝 Dialogue script (please confirm before I generate)
1. [HOOK] "adapted line matching original pattern"
2. [SHOW] "adapted feature call-out for user's product"
3. [DEMO] (silent beat — physical demonstration, no dialogue)
4. [VERDICT] "adapted closing line / CTA"
Total spoken words: ~N | Target duration: Xs | Fits at natural pace: ✅/❌
Approve this dialogue? (yes / edit / rewrite)
Rules:
- This gate is separate from the credit cost confirmation — both must be satisfied
- Never assume approval from earlier confirmations (tone, analysis, credit cost)
- If user says "edit" or proposes changes, revise and re-present until approved
- Skip ONLY if the source video is entirely silent (no speech detected in step 2)
Step 8: Audio decision
Ask the user:
- Enable audio output? (
audioEnabled: true / false)
- Default to
true if source video has speech
- Default to
false if source video is silent
- Supply reference audio for voice cloning?
- Offer to extract the source video's audio and use it as
referenceAudios
- Or user can provide their own voice clip
- Upload via presigned URL if provided
- Sanity probe (if using
audioEnabled: true + referenceImages):
- This combo has a known regression that returns 500
- Before the full call, fire a minimal test to check if the regression is still active
- If still broken, offer fallbacks:
- Drop audio (
audioEnabled: false)
- Drop reference image (text-only, lose brand fidelity)
- Use v2v workaround (generate silent i2v first, then v2v with audio on top)
Step 9: Credit cost estimation
Follow the main SKILL.md's mandatory estimation flow:
- Check
logs/arcads-api.jsonl for matching model + similar config
- Fall back to
MASTER_CONTEXT.md rate table
- For multi-clip: show per-clip and total
- Present with source citation and estimate-only disclosure:
Estimated credit cost:
Seedance 2.0 (15s i2v) × 1 clip × 1 variation = ~0.9 credits
(from logs/arcads-api.jsonl 2026-04-09)
─────────────────────────────────────
Estimated total: ~0.9 credits
⚠️ Estimate only — confirm exact cost in the Arcads platform.
Proceed? (yes/no)
Do NOT generate until the user confirms.
Step 10: Session setup and upload
Follow the main SKILL.md session folder checklist:
GET /v1/products → resolve productId (default from MASTER_CONTEXT.md)
- Check for existing "Arcads API - YYYY-MM-DD" folder → create if missing
- Create project inside the folder → store
projectId
- Upload references via
POST /v1/file-upload/get-presigned-url:
- Product image →
fileType: "image/jpeg" → auto-upscale if longest side < 1024px
- Source video (if v2v mode) →
fileType: "video/mp4"
- Reference audio (if voice clone) →
fileType: "audio/mpeg" or appropriate type
- Store all
filePath values for the generation payload
Step 11: Generate
Compose the CreateVideoDto JSON:
model: "seedance-2.0"
productId, projectId
prompt (from step 6)
aspectRatio: match source video (9:16 or 16:9)
duration: from step 6
resolution: 720p (default)
audioEnabled: from step 8
referenceImages: product image filePath (if i2v mode)
referenceVideos: source video filePath (if v2v mode, product-only, no faces)
referenceAudios: voice clip filePath (if voice clone)
Ask generation count (how many variations? default 1)
Single-clip: Fire N parallel POST /v2/videos/generate calls.
Multi-clip (chained): Fire clips sequentially per the chaining pipeline in step 5.
Each clip depends on the previous clip's output — do not fire in parallel.
Log immediately to logs/arcads-api.jsonl:
{
"timestamp": "...",
"endpoint": "POST /v2/videos/generate",
"model": "seedance-2.0",
"assetId": "...",
"request": { "duration": ..., "resolution": ..., ... },
"response": { "status": "pending", "creditsCharged": ... },
"session": { "folderName": "Arcads API - YYYY-MM-DD", "notes": "clone-ad: ..." }
}
Poll GET /v1/assets/{id} until generated or failed
- Single-clip: poll all variation IDs concurrently
- Multi-clip: poll each clip individually, wait for
generated before proceeding to the next
- Update log entry with final status,
creditsCharged, generationTimeSec, URLs
For multi-clip: upload each completed clip as a fresh presigned URL reference for the next clip (see chaining pipeline in step 5)
Step 12: Present results
- Assign all assets to session project via
POST /v1/assets/add-to-project
- Save all videos to
outputs/clone-ad-tests/ (or a descriptive subfolder)
- Open the output folder on the user's machine so they can immediately review:
open "outputs/clone-ad-tests/" # macOS
- Present watch/download URLs
- For multiple variations: numbered list for comparison
- For multi-clip:
- Show credit summary (total
creditsCharged across all clips/variations)
Seedance 2.0 constraints (quick reference)
Check reference.md for full details. These are the ones most
likely to bite during clone-ad:
| Constraint |
Impact |
referenceVideos + referenceImages mutually exclusive |
Cannot combine in same request (500) |
| v2v with human faces in reference video |
Content checker rejects, credits still charged |
audioEnabled: true + referenceImages regression |
May return 500 — sanity probe first |
referenceVideos count > 1 fails |
Only 1 reference video accepted despite docs saying 3 |
| Content check bills before checking |
Credits charged at create time, not refunded on rejection |
endFrame non-functional on Seedance 2.0 |
Do not use |
| Prompt length |
100–260 words (Seedance sweet spot) |
| Duration |
4–15 seconds (continuous integer) |
| Aspect ratio |
9:16 or 16:9 only (no 1:1) |
| Forbidden words |
cinematic, professional, stunning, 8k, studio, perfect |
Error recovery
| Error |
Recovery |
| Content checker rejects prompt |
Do NOT retry same payload. Remove potentially flagged language. Tighten motion descriptions. Check for forbidden words. |
500 on audioEnabled: true + referenceImages |
Audio+image regression is active. Fallback options: (a) drop audio, (b) drop image and go text-only, (c) v2v workaround: generate silent i2v first, then run v2v with audio on top using the i2v output as reference video |
| v2v face rejection |
Source video has humans — switch to i2v mode with user's product image |
| Prompt too long (> 260 words) |
Trim: cut filler from tone direction, compress setting details, shorten consistency anchors. Prioritize beat structure and dialogue. |
| Source video > 15s |
Split into clips at natural beat boundaries. Generate each separately. Offer to stitch. |
Generation fails (status: failed) |
Check data.error.message. If content-related, rewrite prompt. If server error, wait and retry once. |
Related files
1---2name: clone-ad3description: Clone an existing video ad for a different product or offer. Analyzes the source video's style, pacing, camera work, dialogue, and tone, then adapts and generates a new Seedance 2.0 video customized for the user's product. End-to-end workflow: input video → analysis → adapted prompt → generation → delivery. Use when someone says "clone this ad", "make this ad but for my product", "recreate this video for my brand", or provides a video ad and a product image asking for a similar video.4---5
6# Clone ad — Seedance 2.0
7
8Clone an existing video ad for a different product or offer. The agent analyzes the
9source video frame-by-frame, transcribes dialogue, extracts the visual style and
10beat structure, then generates a new Seedance 2.0 video adapted for the user's product.
11
12**How this differs from analyze-video:**
13- **analyze-video** → output is a **reusable markdown template** saved to `prompt-library/`
14- **clone-ad** → output is a **generated Seedance 2.0 video** delivered to the user
15
16## Prerequisites
17
18Before starting, verify:
19
20```bash
21which ffmpeg || echo "MISSING — run: brew install ffmpeg"
22python3 -c "import whisper; print('whisper OK')" 2>/dev/null || echo "MISSING — run: pip3 install openai-whisper"
23```
24
25Both `extract-frames.sh` and whisper depend on ffmpeg. If missing, install via `brew install ffmpeg` before proceeding.
26
27## Workflow
28
29### Step 0: Gather inputs
30
31Collect from the user:
32
33| Input | Required | Notes |
34|-------|----------|-------|
35| **Source video** | yes | The video ad to clone. File path to `.mp4`, `.mov`, `.webm` |
36| **Product image** | recommended | Reference photo of the user's product. Becomes `referenceImages` / `@(img1)` in the prompt. Without this, Seedance invents its own product design. |
37| **Product/offer description** | if no image | Text description of the product, its features, target audience, and key selling points. Used to rewrite dialogue and product references. |
38| **Brand voice** | optional | Check `MASTER_CONTEXT.md` for brand blocks. If empty, ask the user for tone/audience preferences. |
39
40If the user only provides a video and says "clone this for my product," ask them for
41at least a product image or a text description before proceeding.
42
43### Step 1: Extract frames and audio
44
45Reuse the analyze-video extraction script — do NOT duplicate it.
46
47```bash
48bash "skills/arcads-external-api/prompting/analyze-video/scripts/extract-frames.sh" \
49 "<source_video_path>" "/tmp/clone-ad-analysis" <num_frames>
50```
51
52**Frame count by duration:**
53
54| Source duration | Frames |
55|-----------------|--------|
56| Under 10s | 8 |
57| 10–20s | 12 |
58| 20–30s | 16 |
59| Over 30s | 20 |
60
61**Outputs:**
62- `frame_001.jpg` through `frame_NNN.jpg`
63- `audio.wav` (16 kHz mono, whisper-ready)
64- `metadata.txt` (duration, resolution, fps, frame count)
65
66Read `metadata.txt` to get the source video duration — you'll need it for step 6.
67
68### Step 2: Transcribe audio
69
70Use whisper to get the exact dialogue. This is critical — the dialogue pattern is what
71gets adapted for the user's product.
72
73```python
74import whisper
75model = whisper.load_model("base")
76result = model.transcribe("/tmp/clone-ad-analysis/audio.wav")
77```
78
79Record:
80- Full transcript text
81- Per-segment timestamps and text (`result["segments"]`)
82- Total word count
83- Language detected
84
85If the video is **silent** (no speech detected), note that and skip the dialogue
86adaptation in step 7. The clone will be a visual-style clone only.
87
88### Step 3: Compressed analysis
89
90Read **ALL** extracted frames visually. For each frame, note:
91
92**Structure and pacing:**
93- How many distinct beats/shots are there?
94- What's the narrative arc? (hook → demo → verdict? reveal → detail → CTA?)
95- How long does each beat last? (map to segment timestamps)
96
97**Camera and framing:**
98- POV style: selfie/handheld, tripod, propped phone, over-the-shoulder?
99- Framing per beat: wide, medium, close-up, macro?
100- Camera movement: static, pan, dolly, handheld shake?
101- Signature framing moves (e.g., "leans into camera," "tilts product toward lens")
102
103**Edit style:**
104- Transition type: jump cuts, dissolves, match cuts?
105- Visual rhythm: fast cuts vs held shots?
106- Any recurring motif (e.g., "every other beat is an extreme close-up")?
107
108**Dialogue and script structure:**
109- Hook format: question, statement, exclamation, reaction?
110- Speech pattern: casual/formal, filler words, trailing thoughts, mid-sentence cuts?
111- How many spoken lines? How many silent beats?
112- CTA style: direct ("link in bio"), soft ("you need to try this"), none?
113
114**Tone and energy:**
115- Emotion words that describe the speaker/mood
116- Energy arc: starts calm → builds excitement? Flat? Burst then settle?
117- Speaker's relationship to viewer: friend, expert, skeptic, fan?
118
119**Lighting and technical quality:**
120- Light source: natural/artificial, direction, quality
121- Camera quality: phone/DSLR/cinema, intentional flaws?
122- Audio quality: phone mic, studio, car, outdoor?
123
124**Product references:**
125- How is the product physically shown? (held up, worn, applied, on a surface)
126- What specific claims or features are called out?
127- Brand mentions, labels visible, text overlays?
128
129**What makes this ad distinctive (2–3 defining traits):**
130- The unique combination of elements that makes this ad recognizable
131- These are the traits that MUST transfer to the clone
132
133Store this analysis internally — it does NOT get saved as a template file.
134
135### Step 4: Present analysis summary
136
137Show the user a structured breakdown before proceeding:
138
139```
140📋 Source video analysis
141
142Duration: Xs | Beats: N | Dialogue: Y words | Style: [style name]
143
144Beat map:
145 [00:00–00:03] HOOK — close-up, excited expression, "opening line"
146 [00:03–00:07] SHOW — tilts product to camera, "feature call-out"
147 [00:07–00:10] DEMO — (silent) applies/uses product, close-up on texture
148 [00:10–00:15] VERDICT — back to camera, "closing line + CTA"
149
150Defining traits:
151 1. [trait 1]
152 2. [trait 2]
153 3. [trait 3]
154
155What transfers to your product:
156 ✅ Beat structure, pacing, camera angles, edit style, tone, energy
157 ✅ Dialogue pattern (adapted for your product)
158 ✅ Lighting and technical quality cues
159
160What gets swapped:
161 🔄 Product references → your product
162 🔄 Specific claims → your product's features
163 🔄 Brand mentions → your brand (if provided)
164
165Proceed with adaptation? (yes / adjust)
166```
167
168Wait for user confirmation before continuing.
169
170### Step 5: Decide generation mode
171
172Walk through this decision tree:
173
174```
175┌─ Source video ≤ 15s?
176│ YES → Single-clip generation
177│ NO → Multi-clip split at natural beat boundaries
178│ Each clip ≤ 15s (Seedance max)
179│ Identify best split points from beat map
180│ Use the CHAINED MULTI-CLIP PIPELINE below
181│
182├─ User provided a product IMAGE?
183│ YES → Image-to-video mode (referenceImages with @(img1) in prompt)
184│ For multi-clip: use i2v for clip 1 ONLY, then chain v2v for clips 2+
185│ NO → Text-only mode (describe product in prompt text only)
186│ OR v2v if:
187│ - Source video has NO human faces
188│ - AND user wants to preserve exact visual style
189│ - (v2v with faces → content checker rejection + billed)
190│
191├─ Source video has person SPEAKING?
192│ YES → audioEnabled: true (confirm with user)
193│ Dialogue confirmation gate REQUIRED (step 7)
194│ NO → audioEnabled: false (or ask user preference)
195│ Skip dialogue gate
196│
197└─ User wants voice clone from source audio?
198 YES → Upload source audio as referenceAudios
199 (check audio+image regression: run sanity probe first)
200 NO → Seedance generates its own voice from text
201```
202
203### Chained multi-clip pipeline (confirmed 2026-04-10)
204
205When the source ad is longer than 15s, use this hybrid i2v→v2v chaining pattern for visual continuity:
206
207```
208Clip 1: i2v mode
209 - referenceImages: [product image] ← establishes brand fidelity
210 - audioEnabled: true (if speech)
211 - Generate → poll → download output
212
213Clip 2: v2v mode
214 - referenceVideos: [clip 1 output] ← inherits hands, surface, lighting, product
215 - NO referenceImages (mutually exclusive)
216 - audioEnabled: true (if speech)
217 - Upload clip 1 output via fresh presigned URL
218 - Generate → poll → download output
219
220Clip 3: v2v mode
221 - referenceVideos: [clip 2 output] ← chain from MOST RECENT clip, not clip 1
222 - Upload clip 2 output via fresh presigned URL
223 - Generate → poll → download output
224
225...continue for clips 4+
226```
227
228**Critical rules for chaining:**
2291. **Always chain from the most recent clip** — do not reuse earlier uploads. Presigned URLs expire and stale uploads may fail silently.
2302. **Upload each clip output fresh** via `POST /v1/file-upload/get-presigned-url` immediately before using it as a reference. Do not reuse `filePath` values from previous uploads.
2313. **Wait for each clip to reach `generated` status** before uploading it as a reference for the next clip. Do not fire clips in parallel — they must be sequential.
2324. **Clip 1 uses i2v** for brand fidelity (product image as reference). All subsequent clips use **v2v** (previous clip as reference) for visual continuity.
2335. After all clips are generated, **stitch with ffmpeg**: `ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4` (use absolute paths in the list file).
234
235**Why chaining works:** Seedance v2v inherits the visual style, hands, surface, lighting, and product appearance from the reference video. By chaining clip N → clip N+1, each subsequent clip maintains continuity with the one before it. The first clip's i2v reference image establishes the product identity; v2v propagates it through the series.
236
237**Cost note:** Clip 1 costs the i2v rate (~0.06/sec, 0.9 cr at 15s). Clips 2+ cost the v2v rate (~0.1/sec, 1.5 cr at 15s). A 3-clip series costs ~0.9 + 1.5 + 1.5 = ~3.9 credits total.
238
239**Important constraints to check:**
240- `referenceImages` and `referenceVideos` are **mutually exclusive** — pick one per call
241- v2v with human-containing reference videos → content checker rejection (credits burned)
242- `audioEnabled: true` + `referenceImages` may 500 (intermittent server regression) — sanity probe first
243- `referenceVideos` count > 1 fails — only 1 ref video works
244- If using v2v: only use product-only/abstract/hands-only videos (no faces)
245- Hands-only clips (no face visible) pass the v2v content checker — confirmed 2026-04-10
246
247Tell the user which mode you're using and why.
248
249### Step 6: Adapt for user's product
250
251This is the creative core. Using the analysis from step 3:
252
253**Dialogue adaptation (if source has speech):**
254- Keep the **same conversational pattern**: if the source uses a question hook, use a question hook. If it uses filler words ("like," "okay so"), keep filler words.
255- Keep the **same number of spoken lines** and **same silent beat placement**
256- Keep the **same energy arc** (excited → calm, or flat, or building)
257- Replace **product-specific references** with the user's product name, features, and claims
258- Match the **word count** of each line closely (±3 words per beat) to preserve pacing
259- Read the adapted dialogue out loud at natural pace — it must fit the target duration
260
261**Visual adaptation:**
262- Keep the analyzed camera work, framing per beat, and edit style
263- Replace the product description with the user's product (physical appearance, colors, materials, label details)
264- Keep the setting, lighting, and atmosphere
265- Keep the person description (or adapt if user specifies a different persona)
266- Keep the technical flaw cues (phone quality, mic type, lighting imperfections)
267
268**Prompt composition:**
269- Read [seedance-2.md](../prompt-library/seedance-2.md) for platform rules before composing
270- Read the closest matching style template (e.g., [seedance-2-ugc.md](../prompt-library/seedance-2-ugc.md) for UGC-style sources) for structural guidance
271- Follow the **Subject + Action + Camera + Style + Constraints** order
272- Stay within **100–260 words** (Seedance sweet spot)
273- Include `@(img1)` token if user provided a product image
274- Add consistency anchors: "The product from @(img1) must remain visually unchanged in every shot"
275- Add pacing cues in the tone direction paragraph
276- Use timestamps `[00:00]`, `[00:04]`, etc. for multi-beat sequences
277- **No forbidden words:** cinematic, professional, stunning, 8k, studio, perfect
278
279**Duration selection:**
280- If source ≤ 15s: match source duration (or round to nearest second in 4–15 range)
281- If source > 15s: split into clips, each ≤ 15s
282- Use dialogue word count to validate (see main SKILL.md duration table: ~2.5 words/sec)
283
284### Step 7: Dialogue confirmation gate
285
286**MANDATORY** for any clone with spoken dialogue. Follow the exact format from the
287main SKILL.md:
288
289```
290📝 Dialogue script (please confirm before I generate)
291
292 1. [HOOK] "adapted line matching original pattern"
293 2. [SHOW] "adapted feature call-out for user's product"
294 3. [DEMO] (silent beat — physical demonstration, no dialogue)
295 4. [VERDICT] "adapted closing line / CTA"
296
297Total spoken words: ~N | Target duration: Xs | Fits at natural pace: ✅/❌
298
299Approve this dialogue? (yes / edit / rewrite)
300```
301
302**Rules:**
303- This gate is **separate** from the credit cost confirmation — both must be satisfied
304- Never assume approval from earlier confirmations (tone, analysis, credit cost)
305- If user says "edit" or proposes changes, revise and re-present until approved
306- Skip ONLY if the source video is entirely silent (no speech detected in step 2)
307
308### Step 8: Audio decision
309
310Ask the user:
311
3121. **Enable audio output?** (`audioEnabled: true` / `false`)
313 - Default to `true` if source video has speech
314 - Default to `false` if source video is silent
3152. **Supply reference audio for voice cloning?**
316 - Offer to extract the source video's audio and use it as `referenceAudios`
317 - Or user can provide their own voice clip
318 - Upload via presigned URL if provided
3193. **Sanity probe** (if using `audioEnabled: true` + `referenceImages`):
320 - This combo has a known regression that returns 500
321 - Before the full call, fire a minimal test to check if the regression is still active
322 - If still broken, offer fallbacks:
323 - Drop audio (`audioEnabled: false`)
324 - Drop reference image (text-only, lose brand fidelity)
325 - Use v2v workaround (generate silent i2v first, then v2v with audio on top)
326
327### Step 9: Credit cost estimation
328
329Follow the main SKILL.md's mandatory estimation flow:
330
3311. Check `logs/arcads-api.jsonl` for matching `model` + similar config
3322. Fall back to `MASTER_CONTEXT.md` rate table
3333. For multi-clip: show per-clip and total
3344. Present with source citation and estimate-only disclosure:
335
336```
337Estimated credit cost:
338 Seedance 2.0 (15s i2v) × 1 clip × 1 variation = ~0.9 credits
339 (from logs/arcads-api.jsonl 2026-04-09)
340 ─────────────────────────────────────
341 Estimated total: ~0.9 credits
342
343 ⚠️ Estimate only — confirm exact cost in the Arcads platform.
344 Proceed? (yes/no)
345```
346
347**Do NOT generate until the user confirms.**
348
349### Step 10: Session setup and upload
350
351Follow the main SKILL.md session folder checklist:
352
3531. `GET /v1/products` → resolve `productId` (default from `MASTER_CONTEXT.md`)
3542. Check for existing "Arcads API - YYYY-MM-DD" folder → create if missing
3553. Create project inside the folder → store `projectId`
3564. Upload references via `POST /v1/file-upload/get-presigned-url`:
357 - Product image → `fileType: "image/jpeg"` → auto-upscale if longest side < 1024px
358 - Source video (if v2v mode) → `fileType: "video/mp4"`
359 - Reference audio (if voice clone) → `fileType: "audio/mpeg"` or appropriate type
3605. Store all `filePath` values for the generation payload
361
362### Step 11: Generate
363
3641. Compose the `CreateVideoDto` JSON:
365 - `model: "seedance-2.0"`
366 - `productId`, `projectId`
367 - `prompt` (from step 6)
368 - `aspectRatio`: match source video (`9:16` or `16:9`)
369 - `duration`: from step 6
370 - `resolution`: `720p` (default)
371 - `audioEnabled`: from step 8
372 - `referenceImages`: product image `filePath` (if i2v mode)
373 - `referenceVideos`: source video `filePath` (if v2v mode, product-only, no faces)
374 - `referenceAudios`: voice clip `filePath` (if voice clone)
375
3762. Ask generation count (how many variations? default 1)
377
3783. **Single-clip:** Fire N parallel `POST /v2/videos/generate` calls.
379 **Multi-clip (chained):** Fire clips **sequentially** per the chaining pipeline in step 5.
380 Each clip depends on the previous clip's output — do not fire in parallel.
381
3824. **Log immediately** to `logs/arcads-api.jsonl`:
383 ```json
384 {
385 "timestamp": "...",
386 "endpoint": "POST /v2/videos/generate",
387 "model": "seedance-2.0",
388 "assetId": "...",
389 "request": { "duration": ..., "resolution": ..., ... },
390 "response": { "status": "pending", "creditsCharged": ... },
391 "session": { "folderName": "Arcads API - YYYY-MM-DD", "notes": "clone-ad: ..." }
392 }
393 ```
394
3955. Poll `GET /v1/assets/{id}` until `generated` or `failed`
396 - Single-clip: poll all variation IDs concurrently
397 - Multi-clip: poll each clip individually, wait for `generated` before proceeding to the next
398 - Update log entry with final status, `creditsCharged`, `generationTimeSec`, URLs
399
4006. For multi-clip: upload each completed clip as a fresh presigned URL reference for the next clip (see chaining pipeline in step 5)
401
402### Step 12: Present results
403
4041. **Assign all assets to session project** via `POST /v1/assets/add-to-project`
4052. **Save all videos** to `outputs/clone-ad-tests/` (or a descriptive subfolder)
4063. **Open the output folder** on the user's machine so they can immediately review:
407 ```bash
408 open "outputs/clone-ad-tests/" # macOS
409 ```
4104. Present watch/download URLs
4115. For multiple variations: numbered list for comparison
4126. For multi-clip:
413 - Present each clip separately
414 - Stitch with ffmpeg using **absolute paths**:
415 ```bash
416 printf "file '%s'\n" "$(pwd)/clip1.mp4" "$(pwd)/clip2.mp4" "$(pwd)/clip3.mp4" > /tmp/stitch-list.txt
417 ffmpeg -y -f concat -safe 0 -i /tmp/stitch-list.txt -c copy stitched-output.mp4
418 ```
419 - Provide both stitched file and individual clips
4207. Show credit summary (total `creditsCharged` across all clips/variations)
421
422## Seedance 2.0 constraints (quick reference)
423
424Check [reference.md](../../reference.md) for full details. These are the ones most
425likely to bite during clone-ad:
426
427| Constraint | Impact |
428|-----------|--------|
429| `referenceVideos` + `referenceImages` mutually exclusive | Cannot combine in same request (500) |
430| v2v with human faces in reference video | Content checker rejects, credits still charged |
431| `audioEnabled: true` + `referenceImages` regression | May return 500 — sanity probe first |
432| `referenceVideos` count > 1 fails | Only 1 reference video accepted despite docs saying 3 |
433| Content check bills before checking | Credits charged at create time, not refunded on rejection |
434| `endFrame` non-functional on Seedance 2.0 | Do not use |
435| Prompt length | 100–260 words (Seedance sweet spot) |
436| Duration | 4–15 seconds (continuous integer) |
437| Aspect ratio | `9:16` or `16:9` only (no `1:1`) |
438| Forbidden words | cinematic, professional, stunning, 8k, studio, perfect |
439
440## Error recovery
441
442| Error | Recovery |
443|-------|----------|
444| Content checker rejects prompt | Do NOT retry same payload. Remove potentially flagged language. Tighten motion descriptions. Check for forbidden words. |
445| 500 on `audioEnabled: true` + `referenceImages` | Audio+image regression is active. **Fallback options:** (a) drop audio, (b) drop image and go text-only, (c) v2v workaround: generate silent i2v first, then run v2v with audio on top using the i2v output as reference video |
446| v2v face rejection | Source video has humans — switch to i2v mode with user's product image |
447| Prompt too long (> 260 words) | Trim: cut filler from tone direction, compress setting details, shorten consistency anchors. Prioritize beat structure and dialogue. |
448| Source video > 15s | Split into clips at natural beat boundaries. Generate each separately. Offer to stitch. |
449| Generation fails (`status: failed`) | Check `data.error.message`. If content-related, rewrite prompt. If server error, wait and retry once. |
450
451## Related files
452
453- [analyze-video/SKILL.md](../analyze-video/SKILL.md) — the template-creation cousin (creates reusable `.md` templates instead of generating)
454- [analyze-video/scripts/extract-frames.sh](../analyze-video/scripts/extract-frames.sh) — frame + audio extraction (reused by this skill)
455- [seedance-2.md](../prompt-library/seedance-2.md) — Seedance 2.0 platform rules (read before composing any prompt)
456- [seedance-2-ugc.md](../prompt-library/seedance-2-ugc.md) — 9-layer UGC formula (use as structural reference for UGC-style source videos)
457- [seedance-2-premium-reveal.md](../prompt-library/seedance-2-premium-reveal.md) — premium reveal formula (for dark-void product-only source videos)
458- [seedance-2-product-hero.md](../prompt-library/seedance-2-product-hero.md) — product hero formula (for elemental/effects product-only source videos)
459- [seedance-2-studio-lookbook.md](../prompt-library/seedance-2-studio-lookbook.md) — studio lookbook formula (for polished voiceover-style source videos)
460- [seedance-2-feature-walkthrough.md](../prompt-library/seedance-2-feature-walkthrough.md) — feature walkthrough formula (for fast-paced demo source videos)
461- [../../reference.md](../../reference.md) — API routes, `CreateVideoDto` schema, polling, constraints
462- [../../SKILL.md](../../SKILL.md) — main execution checklist (session setup, dialogue gate, credit estimation, logging)