$npx -y skills add gooseworks-ai/goose-skills --skill render-brand-identity-revealRender a 'brand identity reveal' video from a config — a single poster frame in a real, softly-lit space (real wall, soft-focus plant in the corner, dappled leaf shadow, illuminated poster) whose artwork HARD-CUTS through ~10 on-brand poster mockups (hero product, IG post, hangin
| 1 | # render-brand-identity-reveal |
| 2 | |
| 3 | Render the 'brand identity reveal' format from a config. The signature is a single fixed |
| 4 | poster frame in a REAL, softly-lit space (the illuminated poster-frame look of a |
| 5 | boutique/cinema): a real wall, a real soft-focus plant in the lower-left corner, dappled |
| 6 | leaf shadow. The artwork INSIDE the frame HARD-CUTS (no crossfade) through 11 beats — 10 |
| 7 | on-brand poster mockups + a brand END CARD held ~3s. Music bed only, NO voiceover; copy is |
| 8 | baked into each mockup, never overlaid as captions. |
| 9 | |
| 10 | This capability is the **FREE** assembly only. The paid parts are separate generic |
| 11 | capabilities the recipe names — `create-image-fal` (the one-shot environment plate) and |
| 12 | `create-music-elevenlabs` (the bed). Never re-implement them here. |
| 13 | |
| 14 | ## Three layers |
| 15 | |
| 16 | 1. **Environment plate** (PAID, `create-image-fal`, flux-pro ultra, 9:16) — an *empty* lit |
| 17 | poster frame in a real space, high-res so the camera can be pushed closer by cropping. |
| 18 | Pick a wall color that makes the brand's poster colors POP (complement of the dominant hue). |
| 19 | 2. **Mockups** (FREE) — real-DOM HTML/CSS (`scene.html`), one poster per beat, built from the |
| 20 | brand's real assets + approved copy, frame-stepped via Playwright (`render_art.py`, bare |
| 21 | mode, device_scale_factor 2). |
| 22 | 3. **Composite** (FREE) — `measure_frame.py` detects the blank poster interior quad; |
| 23 | `composite.py` perspective-warps each poster into it AND multiplies the plate's real |
| 24 | leaf-shadow/light back onto the poster (so it reads as behind glass) + a glass sheen; |
| 25 | `build_video.sh` sequences the frames with the music bed. |
| 26 | |
| 27 | ## Inputs |
| 28 | |
| 29 | - `config.json` — copy `scripts/config.example.json` and edit (canvas, plate prompt + |
| 30 | wall_style, camera crop, per-beat durations, end-card copy). Schema + per-file working-dir |
| 31 | layout are documented in `scripts/PIPELINE.md`. |
| 32 | - The brand's REAL product/packaging/lifestyle stills, wordmark, and icon (recreate the icon |
| 33 | as an SVG `<mask>` if the only source has an occluding element). Approved copy only. |
| 34 | |
| 35 | ## Workflow (free assembly) |
| 36 | |
| 37 | ```bash |
| 38 | CAP=skills/ads/capabilities/render-brand-identity-reveal |
| 39 | RUN=<project>/working # holds scene.html + assets/ + the create-image-fal plate in bg/ |
| 40 | |
| 41 | python3 $CAP/scripts/recrop.py 0.72 0.13 # camera distance (bigger frac = bigger frame) |
| 42 | python3 $CAP/scripts/measure_frame.py # detect the blank poster interior quad |
| 43 | python3 $CAP/scripts/render_art.py # render each poster standalone (Playwright, dsf 2) |
| 44 | python3 $CAP/scripts/composite.py # warp into frame + shadow multiply + sheen |
| 45 | bash $CAP/scripts/build_video.sh $RUN/concat.txt $RUN/music.mp3 out.mp4 13.05 1.0 |
| 46 | ``` |
| 47 | |
| 48 | Then `watch` the master (music-only, every poster legible, shadow falls across the art, end |
| 49 | card holds). See `scripts/PIPELINE.md` for adapting `scene.html` per brand. |
| 50 | |
| 51 | ## Rules |
| 52 | |
| 53 | - Approved brand copy ONLY — never invent claims, customers, results, or testimonials. |
| 54 | - Toggle beats with OPACITY, not `display` (a per-state `display:flex` silently overrides a |
| 55 | `display:none` toggle and paints one state over all others). |
| 56 | - Camera distance = re-crop the high-res plate (`recrop.py`), don't regenerate. |
| 57 | - The realism trick = MULTIPLY the plate's real shadow/light back onto each composited poster. |
| 58 | - Music bed only, no VO. Close on the brand end card. |
| 59 | |
| 60 | ## Failure Modes |
| 61 | |
| 62 | - Every rendered frame identical → a per-beat `display:` rule beat the visibility toggle; use |
| 63 | opacity. |
| 64 | - Playwright `evaluate(fn, arg)` didn't switch state in a loop → bake the beat index into the |
| 65 | JS string and return the applied state to assert it. |
| 66 | - Composited poster looks pasted-on → you skipped the shadow multiply (shadow_strength ~0.85). |
| 67 | - Studio product won't cut out (white cap == seamless bg) → present as a photo-tile, don't |
| 68 | corner-flood-fill. |
| 69 | - Playwright missing under node → use the python playwright + cached chromium. |