---
name: video-ad-from-references
description: Makes a new version of a brand's own best-running video ad with their product in Icarus, or as many versions as asked, each in a new setting, cast or mood but with the ad's camera, cuts and timing. Takes their ads from the Meta Ad Library, sends one muted to Icarus's Main Character once per version with the product pinned, then puts the ad's own sound back with ffmpeg. Use when someone gives a product link or product photos and asks for a video ad, a test ad, a Reel, ad variations, "make 5 versions of our ad" or "make an ad like their ads", or sends a Meta Ad Library link or ad videos to copy.
---

# Video ad from references

## Overview

Each new ad is one of the brand's own ads made again: the same camera, motion, timing and cuts, with their product in it, and one or two things changed so it is a new ad, not a copy: the setting, the cast, the light or the occasion. One version unless they ask for more; when they do, each is different from the others. Four steps: get their ads, mute one, have Icarus make each version with the product pinned, put the sound back on each.

The video is sent muted, and the remake is made muted, because the video model plays a reference clip's song back into its own sound and the copyright check then refuses it. The ad's own sound goes back on afterwards with ffmpeg.

**No ads, no render.** Credits are spent only on a real ad you downloaded: theirs, or the best in their niche when theirs are weak. If you cannot get one, stop, spend nothing, and ask for their ad videos.

Asking for the ad is the go-ahead: once you have a reference, run through without stopping for a yes. Stop only for what you cannot decide: which of two pages is the real brand, a feature the product page does not show, a real person's face.

Every Icarus tool is written here as `Icarus:<tool>`. The scripts need `ffmpeg`, Python 3 and, for the Ad Library, Node with Playwright. If `node -e "require('playwright')"` fails, install it once:

```bash
npm i --prefix ~/.cache/ad-library playwright && npx --prefix ~/.cache/ad-library playwright install chromium
export PLAYWRIGHT_PATH=~/.cache/ad-library/node_modules/playwright
```

## Workflow

Copy this checklist and tick it off as you go:

```
Ad progress:
- [ ] 1. Product saved
- [ ] 2. Their ads downloaded (else stop, 0 credits)
- [ ] 3. Reference picked and prepared (muted.mp4 + audio.m4a)
- [ ] 4. Muted reference uploaded to Icarus
- [ ] 5. Versions planned (1 unless they ask for more)
- [ ] 6. Each version rendered, muted
- [ ] 7. Each version checked against the reference
- [ ] 8. Sound put back on each
- [ ] 9. Report written
```

**1. Save the product.** They can send a product page, or only a product photo. Save one clear product photo per side with `Icarus:create_product`, and read the product page's facts when there is one. A public image link goes straight in. A photo attached in the chat goes in through `Icarus:save_attached_files` when the app can pass it, otherwise `Icarus:upload_file` (the person picks it in the box); a photo you have as a file goes in the same way as the clip in step 4. With only a photo, the brand comes from the logo on the product; if the photo doesn't show it, ask for the brand's name or website in one message. For a face, use one from `Icarus:list_characters`, or none: a real person's photo goes in an ad only with their OK.

**2. Get their ads.** Take the brand name from the product page (or the logo on the photo) and find their page, then download their top video ads:

```bash
node scripts/ad_library.cjs "Brand name"            # lists pages, exact name first: "<page id>  <name>  (<n> ads)"
node scripts/ad_library.cjs <page id> 6 ad-library   # writes ad-library/ads.json and the top 6 videos as <rank>-<id>.mp4
```

Pick the page whose name matches the brand exactly, and ask only if two could be it. If the script is blocked (exit code 2), use ad videos the user sent.

Their ads are weak when they have no video ads, or none of them has been running for two weeks: a brand stops paying for an ad that doesn't sell, so one still running after weeks is the clearest sign it works. Then find the best in their niche: search the web for the three or four leading brands in their category and market at a similar price, look each up the same way, and take the longest-running video ads across them. Say in the report that the reference is another brand's and why.

If you have none of these, stop: render nothing, spend no credits, and ask for two or three of their ad videos.

**3. Pick and prepare the reference.** In `ads.json`, pick the video ad that has run longest (`startDate`) and shows a product like theirs. When it is another brand's ad, only its camera, cuts, timing and beats are borrowed: every version then also gets a new place, and a new person when the ad shows one (a product-only ad stays product-only), in its prompt (in the brand's own look, from its website and photos), and its sound is not used (step 8). Look at its frames (`bash scripts/review_frames.sh ad.mp4`). Then:

```bash
python3 scripts/prepare.py ad-library/<rank>-<id>.mp4 15   # cuts at the last shot change before 15 s
```

It writes `muted.mp4` and `audio.m4a` and prints `{"muted", "audio", "seconds", "width", "height"}`. The 15 seconds keeps the cost down; the video model takes up to the length `Icarus:list_models` gives as `referenceVideoMaxSec`.

**4. Upload the muted reference.** Call `Icarus:get_upload_link`, which shows the person nothing, then send the file to its `uploadLink`:

```bash
python3 scripts/upload.py <upload link> <dir>/muted.mp4   # prints the file's Icarus link
```

**5. Plan the versions.** Make one, unless they ask for a number ("5 versions", "a few variations": then 3). The first version changes only the product and, when the ad has one, the person: Main Character already makes two or three small, ordinary changes to the place, so the ad stays theirs and looks real. Each further version adds one small change of its own:

| What changes | How | Example prompt line |
|---|---|---|
| Something in the place | `prompt` | The back wall is now pale blue and a wooden shelf with folded clothes stands by the door. |
| A place like theirs | `prompt`, or a place photo as `locationUrl` | A plain white bedroom with a wooden wardrobe on the right and a window on the left, in flat daylight. |
| Cast | the saved cast face (below) in `characterIds` | (from the casting step) |

A video model makes a place look generated when it is told about light, glow or decor. So a new place is an ordinary one, like the brand's own: plain walls, real furniture, a little everyday clutter, the clip's own kind of light and camera. Never write golden hour, glow, sunbeams, fairy lights, candles, neon, pampas or rattan into a prompt unless the person asked for it.

**Who is in it.** When the reference shows people and they have no saved model of their own in `Icarus:list_characters`, cast the person the brand would cast. Read their kind of people off their website photos and their ads (`python3 scripts/brand_kit.py https://<brand site> brand-kit` downloads the site's photos): age, the mix of looks, face shape, skin tone range, makeup in exact small words (dewy skin, light flush, brushed brows, nude lips, no eyeliner: Muse turns no makeup words into a bare face and "glam" into heavy glam), hair and grooming, build, expression, clothes. Then make three casting options in one `Icarus:create_generations` call with `model` `muse`, frame 3:4, each one short plain line that differs in one thing (hair, skin tone, the mix of looks), put them on one sheet under crops of three or four of their faces, and pick from that sheet the one that fits their people best and is clearly not one of their models; if none fits, one more set of three, then say so and stop. Save the winner with `Icarus:create_character` (the casting photo of a made-up person is their original) and pass its id as `characterIds` to `Icarus:main_character` in every version, so the video holds that exact face; a face only written in words comes out smooth and stiff. A product-only reference stays product-only.

Rules for each version's `prompt`, because Main Character follows it word for word:

- Say what it becomes, in concrete things you could film: colours, materials, objects. "Different", "new" or "another" alone gives the model nothing to draw. Leave the light and the camera look as the clip has them.
- One resolved choice per line: no "or", no "if", no options.
- Every version differs from the reference and from the other versions on what it changes; the product stays pinned in all of them.
- Leave out ids, links, other brands, and any words on screen (Main Character takes text out).
- With people in it, say how they look and move: natural, understated expressions, a relaxed mouth and a soft smile at most, no wide grins or squinting, and hands only where the reference puts them. Without that line, video models overact faces and hands.
- Stay under the length the `prompt` field allows.

Pair lists by position (version 1 gets setting 1 and face 1); never make every combination.

**6. Make each version, muted, with Main Character.** Read the balance with `Icarus:whoami` first. For each version, in order, call `Icarus:main_character` with:

- `clipUrl` the muted link, `productIds` the saved product, and that version's `characterIds`, `locationUrl` and `prompt`
- `sound` `false` (the default), `draft` `true` for a test, an `idempotencyKey` per version

It returns `{ generationId }`; if it returns `{ requestId, status: "starting" }`, call it again with only that `requestId`. Then `Icarus:wait_generations` with `timeoutSeconds` 50 or less, again while `allTerminal` is false. Start the next version while one renders; they are independent.

If `Icarus:create_character` refuses the casting photo, use one `Icarus:create_generation` per version instead: `type` `VIDEO`, `videoTab` `create`, `videoReferenceUrls` the muted link, `productIds` the product, `referenceImageUrls` the casting photo when there is one, `duration` the prepared `seconds` rounded up, `generateAudio` `false`, and a prompt that says: copy [Video1]'s camera, motion, framing and timing; replace <the item the ad sells> with [Image1], exactly as in its photo; the person in [Video1] becomes the person in [Image2], with that exact face, hair and skin, in every shot; then that version's change and the line on natural expressions; remove every word, logo and watermark [Video1] shows. Pinned products come first and loose pictures after, so the product is [Image1] and the casting photo [Image2].

**7. Check each version.** Take its link from the `output` that `Icarus:wait_generations` returns, not from `Icarus:get_generation`: that tool shows the silent in-between clip as a card in the chat, before its sound is back. Download it with `?original=1` added to the link and run `bash scripts/review_frames.sh version.mp4`. Look at it beside the reference's frames and the product photo. It passes when the camera and motion follow the reference, the product looks like its photo in every frame (shape, colour, logo, count), its planned change shows, nothing appears or vanishes, and no old text or logo is left. A failed version is made once more with its prompt fixed for what was wrong; if it fails again, report it and carry on with the others.

**8. Put the sound back on each.**

```bash
bash scripts/add_audio.sh version-1.mp4 <dir>/audio.m4a ad-1.mp4
```

The picture keeps its full length: the sound is cut or padded with silence to fit, and the script checks the result has sound and the same length.

When the reference is another brand's ad, its sound is theirs: skip this step and make each version with `sound` `true` instead, which gives new music in the clip's feel, never its song.

**9. Report.**

```markdown
## <Product>: <done> of <planned> versions
**Reference:** <ad id>, running since <date> (<link>)
**Cost:** <credits> credits (balance from Icarus:whoami before and after)
| Version | What changed | File | Camera follows | Product matches | Text gone | Retried |
```

## Examples

<example>
User: Make 3 versions of an ad for https://mokobara.com/products/the-transit-check-in-luggage

`ad_library.cjs "Mokobara"` gives page 877758885907009; six video ads are downloaded. The one running longest (since April) shows hands packing an open green cabin suitcase in a living room. `prepare.py` cuts it at 9.07 s. Three versions are planned, all with the white Transit check-in pinned: 1, only the product swapped (Main Character makes its own small changes to the room); 2, the back wall now pale blue with a bookshelf by the sofa; 3, a plain white bedroom with a wooden wardrobe, in the same flat daylight. Each is made, checked and given the ad's own sound back, and the report lists all three with the credits spent.
</example>

<example>
User: Make an ad for this kurta like their other ads. https://brand.in/products/kurta

The Ad Library is blocked (exit code 2) and no videos were sent. Stop: "I couldn't get any of your ads from the Ad Library. Send two or three of your ad videos and I'll remake one with this kurta. Nothing has been spent."
</example>

<example>
User: Here's our ad video [file] and our new bottle [photo]. Same ad, new bottle.

No library needed: their video is the reference. "Same ad" means one version with only the bottle changed, so the version's prompt is empty. Save the bottle with `Icarus:create_product`, prepare and upload their video, make it with the bottle pinned, and put their sound back.
</example>

## Common mistakes

| Mistake | What happens | Fix |
|---|---|---|
| Sending the reference with its sound, or `generateAudio` on | the model plays the song back and the copyright check refuses the video | muted in, muted out, sound back with `add_audio.sh` |
| Rendering with no real ad | credits spent on a guess | no ads, no render: ask for their videos |
| Another brand's ad used as it is | their people, place and sound end up in this brand's ad | only when the brand's own ads are weak; then a new person, a new place and new sound in every version |
| Copying weak ads of their own | a remake of an ad that doesn't sell | ads not still running after two weeks are weak: take the niche's best instead |
| Leaving the old product's logo or the ad's text | the remake still sells the old product | name each word and logo to remove in the prompt |
| Describing the new product in words | the words fight the photo and the product drifts | pin it and say "exactly as in its photo" |
| Passing a remake from a thumbnail | broken frames ship | `review_frames.sh`, beside the reference and the photo |
| Versions that only say "a different setting" | the model makes the same ad again | name the place, light and objects |
| Every combination of settings and faces | far more versions and credits than asked for | pair lists by position |
| `-shortest` when adding the sound | a short sound track cuts the picture | `add_audio.sh` pads the sound instead |

---

Page: https://withicarus.com/skills/video-ad-from-references
Download: https://icarus.b-cdn.net/skills/video-ad-from-references/v1-bc0b4e91/video-ad-from-references.zip
Install guide for AI apps: https://withicarus.com/skills/video-ad-from-references/llms-install.md
This skill makes photos and videos with Icarus. Connect Icarus to your AI app: https://withicarus.com/mcp
