{"slug":"render-value-prop","title":"render-value-prop","summary":"Render a designed 'value prop' video from a config — 3-5 noun-phrase benefit claims (<=4 words each) revealed sequentially over per-SKU product visuals, one crisp editorial frame per claim (hook sticker -> N claim beats -> brand end card). Deterministic PIL/HTML beat renderer fra","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-11T17:23:12.405567Z","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-value-prop\ndescription: Render a designed 'value prop' video from a config — 3-5 noun-phrase benefit claims (&lt;=4 words each) revealed sequentially over per-SKU product visuals, one crisp editorial frame per claim (hook sticker -&gt; N claim beats -&gt; brand end card). Deterministic PIL/HTML beat renderer frame-stepped via Playwright and encoded with FFmpeg, sound-off legible, hard cuts, uniform pacing. FREE (no paid calls); music is added separately (create-music-elevenlabs). Use for the value-prop format.\nstatus: active</h2>\n<h1>render-value-prop</h1>\n<p>Render a designed 'value prop' video from a config: a hook sticker, then one beat per short noun-phrase benefit claim (&lt;=4 words each — \"Drug-Free\", \"Zero Sugar\", \"NSF Certified\"), each pairing the claim headline with a per-SKU product visual (the hero SKU rotates beat to beat so the eye anchor shifts), then a brand-wordmark end card. Text + product carry the spot — no narration, no talking head — and it is built to be legible sound-off. Every beat is a pure function of beat-local time <code>t</code> (deterministic PIL start frames + Playwright hyperframes + FFmpeg); no CSS keyframes, no setTimeout. FREE (no paid calls); music is a separate capability (create-music-elevenlabs), or ship silent for $0.</p>\n<h2>Run</h2>\n<p><code>render_master.py --config config.json --project &lt;dir&gt;</code> -&gt; <code>&lt;dir&gt;/finals/master-clean.mp4</code> (silent),\n1080x1920, deterministic, $0. The renderer is <strong>fully config-driven</strong> — palette, copy, SKUs,\npacing, hook, logo and end card all come from <code>config.json</code> (schema = <code>ad_sample.recipe.config</code>;\nsee <code>config.example.json</code>). Nothing is hardcoded to one brand. <code>build_storyboard_preview.py</code> is an\noptional free preview gallery for the gate; <code>build_text_overlays.py</code> is optional (transparent\ntext-zone PNGs for compositing claims over a motion clip).</p>\n<p>Environment: run with a <strong>Python that has Playwright</strong> (override the frame-render interpreter with\n<code>RENDER_PYTHON</code>); <code>ffmpeg</code> is auto-discovered (<code>FFMPEG</code> env &gt; PATH &gt; common prefixes). The frame\nrenderer <code>render_hyperframe.py</code> is <strong>bundled</strong> in <code>scripts/</code> — no external atom to fetch.</p>\n<h2>Contract</h2>\n<ul>\n<li>Deterministic + FREE (Playwright frame-step + FFmpeg); no paid calls, no AI-rendered text.</li>\n<li>Claims are noun phrases, &lt;=4 words; never &lt;3, never &gt;5. Optional benefit sentence &lt;=12 words.</li>\n<li>One product visual per beat; rotate which SKU is the hero. Never reuse a flat variety-pack image as every canvas.</li>\n<li>Sound-off legibility is the bar: the headline uses the config <code>palette.ink</code> color on <code>palette.bg</code>;\nthe per-beat <strong>accent</strong> color (from <code>value_props[].accent</code> — a SKU-accent slug or a hex) is the\naccent rule, not the headline.</li>\n<li>Product widths <strong>auto-scale from each image's aspect ratio</strong> (target display height), so tall\nsachet cutouts and wide product packshots both frame correctly.</li>\n<li>Assets are packshots, not always transparent cutouts: set <code>palette.bg</code> to the product image's\nbackground color for seamless compositing (free — avoids a paid background-removal step).</li>\n<li>Uniform pacing (hook ~3.0s, props 2.0-2.5s each, endcard ~2.0s); total lands in the 10-20s window (~17s). No acceleration curve.</li>\n<li>No human face is the focus. End card uses the brand wordmark <strong>image</strong> when a hi-res one\n(aspect &gt;= ~1.2, i.e. a real &gt;=1200x600 wordmark) is provided via <code>config.logo</code>; otherwise it\n<strong>falls back to a typographic <code>brand_name</code> wordmark</strong> (many brands ship only a favicon).</li>\n<li>Music is added separately by create-music-elevenlabs (quiet instrumental bed at -14 dB), or ship silent.</li>\n</ul>\n","files":[{"path":"scripts/build_storyboard_preview.py","sizeBytes":11116,"isText":true},{"path":"scripts/build_text_overlays.py","sizeBytes":6791,"isText":true},{"path":"scripts/config.example.json","sizeBytes":1968,"isText":true},{"path":"scripts/render_hyperframe.py","sizeBytes":4658,"isText":true},{"path":"scripts/render_master.py","sizeBytes":17881,"isText":true},{"path":"shared/animations/registry.yml","sizeBytes":4308,"isText":true},{"path":"shared/animations/sachet-entrance/cascade-from-top.js","sizeBytes":980,"isText":true},{"path":"shared/animations/sachet-entrance/fade-stagger.js","sizeBytes":1013,"isText":true},{"path":"shared/animations/sachet-entrance/slide-in-lateral.js","sizeBytes":1260,"isText":true},{"path":"shared/animations/sachet-entrance/springScale-pop.js","sizeBytes":883,"isText":true},{"path":"shared/animations/sachet-entrance/tilt-fan.js","sizeBytes":1095,"isText":true},{"path":"shared/animations/text-entrance/fade-stagger.js","sizeBytes":1339,"isText":true},{"path":"shared/animations/text-entrance/mask-reveal.js","sizeBytes":1124,"isText":true},{"path":"shared/animations/text-entrance/type-on.js","sizeBytes":1324,"isText":true},{"path":"shared/animations/text-entrance/word-by-word.js","sizeBytes":1896,"isText":true},{"path":"shared/beat-templates/endcard-wordmark.html","sizeBytes":1982,"isText":false},{"path":"shared/beat-templates/hook-sticker.html","sizeBytes":2506,"isText":false},{"path":"shared/beat-templates/prop-hero.html","sizeBytes":2715,"isText":false},{"path":"shared/beat-templates/prop-row.html","sizeBytes":3069,"isText":false},{"path":"shared/_shared.css","sizeBytes":4855,"isText":false},{"path":"shared/_shared.js","sizeBytes":2568,"isText":true},{"path":"SKILL.md","sizeBytes":3534,"isText":true},{"path":"skill.meta.json","sizeBytes":311,"isText":true},{"path":"tests/smoke-test.md","sizeBytes":477,"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:13.71357Z","sha256":"E68102F555BC9C470F028987A99EC4B57EB3901EDCCF75330EEE9A127509934D","sizeBytes":33412},"review":null,"source":{"repositoryUrl":"https://github.com/gooseworks-ai/goose-skills","path":"skills/ads/capabilities/render-value-prop","license":"MIT","commit":"a9f4676e266f9f04786e3f4145baf931f61fc309","subtreeSha":"6B13BD3C59643F3284FE31EEF5A1AC650898764231E1F34968AE01F0B9B25554","lastSyncedAt":"2026-09-24T06:48:52.524221Z"},"reviewedAt":"2026-09-11T17:26:12.714534Z","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-value-prop"},{"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"}]}