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.
74
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
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:
prompt-library/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.
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.
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.jpgaudio.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.
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:
result["segments"])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.
Read ALL extracted frames visually. For each frame, note:
Structure and pacing:
Camera and framing:
Edit style:
Dialogue and script structure:
Tone and energy:
Lighting and technical quality:
Product references:
What makes this ad distinctive (2–3 defining traits):
Store this analysis internally — it does NOT get saved as a template file.
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.
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 textWhen 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:
POST /v1/file-upload/get-presigned-url immediately before using it as a reference. Do not reuse filePath values from previous uploads.generated status before uploading it as a reference for the next clip. Do not fire clips in parallel — they must be sequential.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 callaudioEnabled: true + referenceImages may 500 (intermittent server regression) — sanity probe firstreferenceVideos count > 1 fails — only 1 ref video worksTell the user which mode you're using and why.
This is the creative core. Using the analysis from step 3:
Dialogue adaptation (if source has speech):
Visual adaptation:
Prompt composition:
@(img1) token if user provided a product image[00:00], [00:04], etc. for multi-beat sequencesDuration selection:
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:
Ask the user:
audioEnabled: true / false)
true if source video has speechfalse if source video is silentreferenceAudiosaudioEnabled: true + referenceImages):
audioEnabled: false)Follow the main SKILL.md's mandatory estimation flow:
logs/arcads-api.jsonl for matching model + similar configMASTER_CONTEXT.md rate tableEstimated 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.
Follow the main SKILL.md session folder checklist:
GET /v1/products → resolve productId (default from MASTER_CONTEXT.md)projectIdPOST /v1/file-upload/get-presigned-url:
fileType: "image/jpeg" → auto-upscale if longest side < 1024pxfileType: "video/mp4"fileType: "audio/mpeg" or appropriate typefilePath values for the generation payloadCompose the CreateVideoDto JSON:
model: "seedance-2.0"productId, projectIdprompt (from step 6)aspectRatio: match source video (9:16 or 16:9)duration: from step 6resolution: 720p (default)audioEnabled: from step 8referenceImages: 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
generated before proceeding to the nextcreditsCharged, generationTimeSec, URLsFor multi-clip: upload each completed clip as a fresh presigned URL reference for the next clip (see chaining pipeline in step 5)
POST /v1/assets/add-to-projectoutputs/clone-ad-tests/ (or a descriptive subfolder)open "outputs/clone-ad-tests/" # macOSprintf "file '%s'\n" "$(pwd)/clip1.mp4" "$(pwd)/clip2.mp4" "$(pwd)/clip3.mp4" > /tmp/stitch-list.txt
ffmpeg -y -f concat -safe 0 -i /tmp/stitch-list.txt -c copy stitched-output.mp4creditsCharged across all clips/variations)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 |
|---|---|
| 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. |
.md templates instead of generating)CreateVideoDto schema, polling, constraints0bfafb2
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.