{"slug":"render-vignette","title":"render-vignette","summary":"Assemble a short-form 'vignette' ad from clean product cutouts composited over a kinetic background video — birefnet cutout, then a cold-open text card + product carousel + annotated specimen-sheet end card, plus loudnorm + separate-pass music mux. FREE assembly (PIL + rsvg + FFm","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-11T17:23:12.548174Z","repo":{"url":"https://github.com/gooseworks-ai/goose-skills","stars":1222,"forks":208,"license":"MIT","updatedAt":"2026-09-22T18:53:29Z"},"bodyHtml":"<hr>\n<h2>name: render-vignette\ndescription: Assemble a short-form 'vignette' ad from clean product cutouts composited over a kinetic background video — birefnet cutout, then a cold-open text card + product carousel + annotated specimen-sheet end card, plus loudnorm + separate-pass music mux. FREE assembly (PIL + rsvg + FFmpeg); the recipe supplies the config and gates the paid BG/cutout/music calls to their own capabilities. Use for the vignette format.\nstatus: active</h2>\n<h1>render-vignette</h1>\n<p>Assemble a short-form 'vignette' ad from clean product cutouts composited over a kinetic background video. Motion lives in the BG video; the product rides on top as a static cutout layer. Music-led, zero VO, sub-12s, loopable — it reads muted because the product label + on-screen copy carry the message. Defaults to the V-CARD structure: a cold-open text card → a product carousel under one shared BG → an annotated specimen-sheet end card.</p>\n<h2>Run</h2>\n<ol>\n<li><code>strip_product_backgrounds.py</code> — birefnet cutout of each PDP shot to clean hard-edge alpha (no halo/shadow).</li>\n<li><code>render_overlays.py</code> — PIL + <code>rsvg-convert</code> render the cold-open card (Boska Black, dead-center) + the annotated specimen-sheet end card (brand SVG logo + Space Grotesk annotations) as transparent 1080x1920 PNGs. FREE.</li>\n<li><code>composite_variants.py</code> — one FFmpeg <code>filter_complex</code> per BG variant: BG (palette-aware dim) → cold-open overlay → cutouts (width-anchored, vertically centered <code>y=(H-h)/2</code>) → end card. h264 crf20 yuv420p +faststart 30fps. FREE.</li>\n<li><code>music_and_mux.py</code> — instrumental music bed → <code>acompressor + loudnorm I=-18:TP=-2:LRA=9</code> → muxed into every variant in a SEPARATE pass with explicit <code>-map 0:v:0 -map 1:a:0</code>. The mux is FREE; the music generation is a paid call that in prod routes through create-music-elevenlabs.</li>\n</ol>\n<h2>Contract</h2>\n<ul>\n<li>FREE assembly: birefnet cutout (see gap below) + PIL/rsvg overlays + FFmpeg composite + mux. No AI-rendered text; the product art/labels and on-screen copy are real, never invented.</li>\n<li>The template recipe (DB) supplies the per-brand config (products, cold-open text, end-card lines, BG concept, beat timing). This capability is the generic assembler.</li>\n<li>Craft rules preserved from the source molecule:\n<ul>\n<li>Cutouts stripped clean (no halo/shadow), height-anchored at vertical-center (<code>y=(H-h)/2</code>) so mixed-shape SKUs share one visual mid-line — never bottom-anchor (squat jars jump). For 9:16 scale by WIDTH (~75% tall bottles, ~65% squat jars).</li>\n<li>Palette-aware BG dim: high-contrast/chrome BG → push saturation DOWN hard (<code>saturation=0.50</code>); naturally-contrasty BG → lighter dim (<code>saturation=0.85</code>).</li>\n<li>End card = annotated specimen-sheet (EST year + rule + wordmark + rule + ingredient + positioning + claim), never a bare logo. Use the WHITE logo variant on dark BGs, cream on light.</li>\n<li>Music-led, NO VO — instrumental only (VO/lyrics would fight the cold-open + end-card text). Loudnorm before the mux.</li>\n<li>Mux is a SEPARATE FFmpeg pass with explicit <code>-map 0:v:0 -map 1:a:0</code> (single-pass composite+mux silently ships 1 kbps garbage audio).</li>\n</ul>\n</li>\n</ul>\n<h2>Gaps / routing notes</h2>\n<ul>\n<li><strong>birefnet is a paid FAL model, not free.</strong> <code>strip_product_backgrounds.py</code> calls <code>fal-ai/birefnet/v2</code> directly via a <code>fal_helpers</code> shim (<code>sys.path.insert</code> into a shared atoms dir + <code>from fal_helpers import ...</code>). It is bundled here because the cutout is an intrinsic assembly step, but in prod the birefnet cutout should route through <strong>create-image-fal</strong> (the fal-proxy capability that bills the Ads agent) rather than hitting <code>fal.run</code> directly. Treat the direct-fal path as a gap to close; the recipe gates the cutout to <code>gooseworks fetch create-image-fal</code>.</li>\n<li><strong>Background sourcing is not in this capability.</strong> The kinetic BG is sourced upstream — PEXELS-FIRST (free stock, the key cost lever), falling back to T2V (create-video-fal) only when stock coverage fails — and dropped into <code>source/t2v-outputs/&lt;slug&gt;.mp4</code> so the composite is source-agnostic. There is no Pexels fetcher bundled here; that lives in the recipe's playbook.</li>\n<li><code>music_and_mux.py</code> also uses the <code>fal_helpers</code> shim for the ElevenLabs music generation; in prod that generation routes through <strong>create-music-elevenlabs</strong>, and only the loudnorm + separate-pass mux run locally as FREE assembly.</li>\n</ul>\n","files":[{"path":"scripts/composite_variants.py","sizeBytes":5779,"isText":true},{"path":"scripts/music_and_mux.py","sizeBytes":5953,"isText":true},{"path":"scripts/render_overlays.py","sizeBytes":5531,"isText":true},{"path":"scripts/strip_product_backgrounds.py","sizeBytes":4160,"isText":true},{"path":"SKILL.md","sizeBytes":4280,"isText":true},{"path":"skill.meta.json","sizeBytes":307,"isText":true},{"path":"tests/smoke-test.md","sizeBytes":706,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-11T17:24:14.173706Z","sha256":"BD5A5058C2573729CEB9BA2DF52C18BC2717B0C5F3C6B2A8E24E22769C179E89","sizeBytes":12213},"review":null,"source":{"repositoryUrl":"https://github.com/gooseworks-ai/goose-skills","path":"skills/ads/capabilities/render-vignette","license":"MIT","commit":"a9f4676e266f9f04786e3f4145baf931f61fc309","subtreeSha":"153548C29357230D54F1657BA3DC907A343DA5175EA638E8360E688AF15C2F77","lastSyncedAt":"2026-09-24T06:48:52.524221Z"},"reviewedAt":"2026-09-11T17:26:12.827415Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/gooseworks-ai/goose-skills/tree/main/skills/ads/capabilities/render-vignette"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install gooseworks-ai-goose-skills@llmmart"},{"target":"git","command":"git clone https://github.com/gooseworks-ai/goose-skills.git"}]}