Claude Skill

render-proof-points-overlay

Build the deterministic PIL pill overlays for a 'perfect-score + proof-points' UGC video ad (white 10/10 score header with a medal + orange sub with a finger-down + 3-4 green-check proof pills) and composite them onto a base clip in a diagonal L->R->L->R cascade, then mux the mus

LLM Mart · 0 points · 4 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download gooseworks-ai-goose-skills-skills_ads_capabilities_render-proof-points-overlay-e1592ee.zip · 7 KB
Part of gooseworks-ai/goose-skills — 44 skills

Install

skills CLI npx skills add https://github.com/gooseworks-ai/goose-skills/tree/main/skills/ads/capabilities/render-proof-points-overlay
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install gooseworks-ai-goose-skills@llmmart
Git git clone https://github.com/gooseworks-ai/goose-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole gooseworks-ai/goose-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

render-proof-points-overlay

Build the deterministic PIL/FFmpeg overlays for the "Instagram comparison-tool reviewer" UGC ad — a white "we got a perfect 10/10 score" headline pill (trailing medal), an orange "but here's also why you'll love us" sub pill (trailing finger-down, width-matched to the header), and 3-4 green-check proof pills — then composite them onto a base clip in the format's signature diagonal cascade and mux the music into the master. FREE and deterministic: the pills are PIL-rendered so the score, checks, and wordmark stay pixel-crisp (a video model would smear type). The base clip (create-image-fal keyframe -> create-video-fal i2v) and the music bed (create-music-elevenlabs) come from separate paid capabilities; this one only does the free rendering.

Run

fetch_icons.py --run-dir

Scripts

  • fetch_icons.py — downloads the three Twemoji PNGs (medal 1f3c5, finger-down 1f447, check 2705) to <run>/assets/icons. PIL cannot render Apple Color Emoji, so pills paste Twemoji PNGs. Free, local.
  • build_overlays.py — PIL: renders the white score header (trailing medal), the orange subhead (trailing finger-down, width-matched to the header), and N green-check proof pills auto-sized to their copy. Bold weight and icon-centered-on-pill-middle are load-bearing.
  • compose_master.py — FFmpeg: scale/crop the base clip to 1080x1920@30, composite the always-on headers, cascade the proof pills (each enable='gte(t,T)' on its own alternating LEFT/RIGHT row), mux the music, apply the anti-AI grain pass, re-encode crf23/maxrate12M -> master-final.mp4.

Contract

  • Deterministic + FREE (PIL + FFmpeg); no paid calls, no AI-rendered text — the score, checks, and wordmark are composited, never generated.
  • Config-driven off one config.json (overlays, layout, duration_sec, optional music/post_production); the template recipe supplies the config from recipe.config.
  • Always re-run build_overlays.py before compose_master.py — the compositor reads pre-rendered PNGs and silently reuses stale ones on a copy change.
  • Headers stay on 0-duration and must not cover the bottle face; proof pills cascade one-per-beat down the diagonal (NOT four-corners) — the cascade is the format's signature.
  • Requires Pillow + ffmpeg. No API keys.
Files (goose-skills)
  • scripts
    • build_overlays.py 6.7 KB
      #!/usr/bin/env python3
      """Build the pill PNG overlays for a "perfect-score + proof-points" ad.
      
      Config-driven (reads config.json) so the same engine renders any brand:
      - one persistent white SCORE header pill (trailing medal),
      - one persistent orange SUBHEAD pill (trailing finger-down),
      - 3-4 green-CHECK proof pills (leading check), each auto-sized to its copy.
      
      The reference look (Origins Nutra / SpoiledChild E27) is: bold rounded pills,
      Twemoji icons pasted as PNGs (PIL cannot render Apple Color Emoji), icons
      vertically centered on the pill middle. See SKILL.md Phase 3 for the rules.
      
      Usage:  build_overlays.py --config config.json --out-dir <run>/generated/overlays
      """
      import argparse
      import json
      import pathlib
      from PIL import Image, ImageDraw, ImageFont
      
      # ---- font resolution (bold is load-bearing: regular reads as a generic UI card) ----
      FONT_CANDIDATES = [
          "/System/Library/Fonts/Supplemental/Arial Bold.ttf",
          "/System/Library/Fonts/Supplemental/Arial Rounded Bold.ttf",
          "/System/Library/Fonts/HelveticaNeue.ttc",
          "/System/Library/Fonts/SFNS.ttf",
          "/System/Library/Fonts/Supplemental/Arial.ttf",
      ]
      
      
      def load_font(size):
          for p in FONT_CANDIDATES:
              try:
                  return ImageFont.truetype(p, size)
              except Exception:
                  continue
          return ImageFont.load_default()
      
      
      def measure(draw, text, font):
          b = draw.textbbox((0, 0), text, font=font)
          return b[2] - b[0], b[3] - b[1]
      
      
      class Icons:
          """Loads Twemoji PNGs from an icons dir (check.png / medal.png / finger-down.png)."""
      
          def __init__(self, icons_dir):
              self.dir = pathlib.Path(icons_dir)
              self.cache = {}
      
          def get(self, name):
              if name not in self.cache:
                  self.cache[name] = Image.open(self.dir / name).convert("RGBA")
              return self.cache[name]
      
          def painter(self, name):
              def _paint(target, x, y, size):
                  icon = self.get(name).resize((size, size), Image.LANCZOS)
                  target.alpha_composite(icon, (x, y))
              return _paint
      
      
      def rounded_pill(lines, font, pad_x=36, pad_y=14, bg=(255, 255, 255, 255),
                       fg=(0, 0, 0, 255), radius=28, trailing_icon=None, leading_icon=None,
                       icon_scale=0.95, icon_line=-1, min_width=0, min_height=0):
          """Render one rounded-rect pill. Icon is sized off single-line cap-height and
          pasted inline (trailing = right end of `icon_line`; leading = left of line 0).
          Both icons vertically center on the pill's geometric middle."""
          dummy = Image.new("RGBA", (10, 10))
          d = ImageDraw.Draw(dummy)
          cap = d.textbbox((0, 0), "Hg", font=font)
          cap_h = cap[3] - cap[1]
      
          widths, heights = [], []
          for ln in lines:
              w, h = measure(d, ln, font)
              widths.append(w)
              heights.append(h)
          line_gap = 6
          text_h = sum(heights) + line_gap * (len(lines) - 1)
      
          icon_pad = max(8, int(cap_h * 0.15))
          icon_size = int(cap_h * icon_scale)
      
          target = icon_line if icon_line >= 0 else len(lines) + icon_line
          extra = (icon_pad + icon_size) if trailing_icon else 0
          text_w = max(max(widths), widths[target] + extra)
      
          lead_extra = (icon_pad + icon_size) if leading_icon else 0
          box_w = max(min_width, text_w + 2 * pad_x + lead_extra)
          box_h = max(min_height, text_h + 2 * pad_y)
      
          img = Image.new("RGBA", (box_w, box_h), (0, 0, 0, 0))
          d = ImageDraw.Draw(img)
          d.rounded_rectangle([0, 0, box_w - 1, box_h - 1], radius=radius, fill=bg)
      
          text_x = pad_x + lead_extra
          line_h = max(heights) if heights else 0
          block_h = len(lines) * line_h + line_gap * (len(lines) - 1)
          block_top = (box_h - block_h) // 2
          icon_y = (box_h - icon_size) // 2
      
          if leading_icon:
              leading_icon(img, pad_x, icon_y, icon_size)
      
          for i, ln in enumerate(lines):
              cy = block_top + i * (line_h + line_gap) + line_h // 2
              d.text((text_x, cy), ln, font=font, fill=fg, anchor="lm")
              if trailing_icon and i == target:
                  trailing_icon(img, text_x + widths[i] + icon_pad, icon_y, icon_size)
          return img
      
      
      def tup(v):
          return tuple(v) if isinstance(v, list) else v
      
      
      def main():
          ap = argparse.ArgumentParser()
          ap.add_argument("--config", required=True)
          ap.add_argument("--icons-dir", default=None, help="defaults to <run>/assets/icons")
          ap.add_argument("--out-dir", required=True)
          args = ap.parse_args()
      
          cfg = json.loads(pathlib.Path(args.config).read_text())
          out = pathlib.Path(args.out_dir)
          out.mkdir(parents=True, exist_ok=True)
          icons_dir = args.icons_dir or (pathlib.Path(args.config).resolve().parent / "assets" / "icons")
          icons = Icons(icons_dir)
      
          ov = cfg["overlays"]
      
          # 1. white SCORE header (trailing medal on line index icon_line, default 0)
          h = ov["header"]
          hdr1 = rounded_pill(h["lines"], load_font(h.get("font_size", 54)),
                              pad_x=h.get("pad_x", 38), pad_y=h.get("pad_y", 14),
                              bg=tup(h.get("bg", [255, 255, 255, 245])),
                              fg=tup(h.get("fg", [15, 15, 15, 255])),
                              radius=h.get("radius", 34),
                              trailing_icon=icons.painter(h.get("icon", "medal.png")),
                              icon_scale=h.get("icon_scale", 1.35),
                              icon_line=h.get("icon_line", 0))
          hdr1.save(out / "01-header-white.png")
          print(f"[ov] 01 white header  {hdr1.size}")
      
          # 2. orange SUBHEAD (width-matched to header so the two stack cleanly)
          s = ov["subhead"]
          hdr2 = rounded_pill(s["lines"], load_font(s.get("font_size", 50)),
                              pad_x=s.get("pad_x", 34), pad_y=s.get("pad_y", 10),
                              bg=tup(s.get("bg", [244, 92, 50, 245])),
                              fg=tup(s.get("fg", [255, 255, 255, 255])),
                              radius=s.get("radius", 30),
                              trailing_icon=icons.painter(s.get("icon", "finger-down.png")),
                              icon_scale=s.get("icon_scale", 1.30),
                              min_width=hdr1.size[0])
          hdr2.save(out / "02-header-orange.png")
          print(f"[ov] 02 orange sub    {hdr2.size}")
      
          # 3-N. green-check proof pills (auto-sized to content — NO min_width)
          pf = ov["proof_points"]
          font_check = load_font(ov.get("proof_font_size", 40))
          for i, pp in enumerate(pf, start=3):
              p = rounded_pill([pp["line_a"], pp["line_b"]], font_check,
                               pad_x=24, pad_y=14, radius=24,
                               bg=(255, 255, 255, 248), fg=(15, 15, 15, 255),
                               leading_icon=icons.painter("check.png"), icon_scale=1.0)
              name = f"{i:02d}-check-{pp.get('slug', i)}.png"
              p.save(out / name)
              print(f"[ov] {name}  {p.size}")
      
          print(f"[ov] built {2 + len(pf)} overlays -> {out}")
      
      
      if __name__ == "__main__":
          main()
      
    • compose_master.py 4.3 KB
      #!/usr/bin/env python3
      """Composite the pill overlays onto the base clip in a diagonal cascade, mux the
      music bed, apply the anti-AI grain pass -> master-final.mp4. Config-driven so it
      handles any 3-4 proof-point count.
      
      Assumes overlays already built into <run>/generated/overlays by build_overlays.py
      (the one_shot.py driver runs that first). Positions + reveal times from config.layout.
      
      Cascade signature: pills alternate LEFT / RIGHT down the frame, each revealed at
      its own time via overlay enable='gte(t,T)' — eye follows L->R->L->R on the beat.
      
      Usage:  compose_master.py --config config.json --run-dir <run>
      Output: <run>/master-final.mp4
      """
      import argparse
      import json
      import pathlib
      import subprocess
      
      
      def main():
          ap = argparse.ArgumentParser()
          ap.add_argument("--config", required=True)
          ap.add_argument("--run-dir", required=True)
          ap.add_argument("--no-music", action="store_true", help="skip music mux (silent master)")
          args = ap.parse_args()
      
          cfg = json.loads(pathlib.Path(args.config).read_text())
          run = pathlib.Path(args.run_dir)
          gen = run / "generated"
          ov = gen / "overlays"
          lay = cfg["layout"]
          dur = cfg.get("duration_sec", 10)
      
          clip = gen / "clip-handheld.mp4"
          header = ov / "01-header-white.png"
          subhead = ov / "02-header-orange.png"
          pills = sorted(ov.glob("[0-9][0-9]-check-*.png"))
          if not pills:
              raise SystemExit("no proof pills found in generated/overlays — run build_overlays.py first")
      
          rows = lay["pill_rows_y"]
          times = lay["reveal_times"]
          left_x = lay.get("pill_left_x", 40)
          right_margin = lay.get("pill_right_margin", 40)
      
          inputs = ["-i", str(clip), "-i", str(header), "-i", str(subhead)]
          for p in pills:
              inputs += ["-i", str(p)]
      
          # base scale/crop to 1080x1920 @ 30fps
          fc = [
              "[0:v]scale=1080:1920:force_original_aspect_ratio=increase,"
              "crop=1080:1920,setsar=1,fps=30[base]",
              f"[base][1]overlay={lay['header_x']}:{lay['header_y']}[v1]",
              f"[v1][2]overlay={lay['header_x']}:{lay['subhead_y']}[v2]",
          ]
          prev = "v2"
          for i, _p in enumerate(pills):
              idx = 3 + i             # ffmpeg input index for this pill
              y = rows[i % len(rows)]
              t = times[i % len(times)]
              x = str(left_x) if i % 2 == 0 else f"(W-w-{right_margin})"
              out = f"vp{i}"
              fc.append(f"[{prev}][{idx}]overlay={x}:{y}:enable='gte(t,{t})'[{out}]")
              prev = out
      
          composite = gen / "composite-no-audio.mp4"
          subprocess.run([
              "ffmpeg", "-y", "-hide_banner", "-loglevel", "error", *inputs,
              "-filter_complex", ";".join(fc), "-map", f"[{prev}]",
              "-c:v", "libx264", "-pix_fmt", "yuv420p", "-crf", "18", "-preset", "medium",
              "-movflags", "+faststart", "-t", str(dur), str(composite),
          ], check=True)
          print(f"[composite] {composite}")
      
          # grain master + music mux. grain: eq + hqdn3d + noise; re-encode crf23/maxrate12M
          # (noise inflates bitrate — see memory feedback_grain_pass_inflates_bitrate).
          out = run / "master-final.mp4"
          grain = "[0:v]eq=contrast=1.06:saturation=0.93,hqdn3d=1.5:1.5:3:3,noise=alls=9:allf=t+u[v]"
          music = gen / "music-bed.m4a"
          if args.no_music or not music.exists():
              subprocess.run([
                  "ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", str(composite),
                  "-filter_complex", grain, "-map", "[v]",
                  "-c:v", "libx264", "-pix_fmt", "yuv420p", "-crf", "23",
                  "-maxrate", "12M", "-bufsize", "24M", "-preset", "medium",
                  "-movflags", "+faststart", "-t", str(dur), str(out),
              ], check=True)
          else:
              subprocess.run([
                  "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
                  "-i", str(composite), "-i", str(music),
                  "-filter_complex", grain, "-map", "[v]", "-map", "1:a:0",
                  "-c:v", "libx264", "-pix_fmt", "yuv420p", "-crf", "23",
                  "-maxrate", "12M", "-bufsize", "24M", "-preset", "medium",
                  "-c:a", "aac", "-b:a", "192k",
                  "-movflags", "+faststart", "-t", str(dur), str(out),
              ], check=True)
          print(f"[master] {out}")
          subprocess.run([
              "ffprobe", "-v", "error", "-show_entries",
              "stream=codec_name,width,height,r_frame_rate,duration",
              "-show_entries", "format=duration,bit_rate", "-of", "default=nw=1", str(out),
          ])
      
      
      if __name__ == "__main__":
          main()
      
    • fetch_icons.py 1.1 KB
      #!/usr/bin/env python3
      """Download the three Twemoji PNGs the pills need into <run>/assets/icons.
      
      PIL cannot render Apple Color Emoji (horizontal-bar artifacts) — we paste 72x72
      Twemoji PNGs instead (see memory feedback_pil_emoji_use_twemoji_png). Free, local.
      
      Usage:  fetch_icons.py --run-dir <run>
      """
      import argparse
      import pathlib
      import urllib.request
      
      CDN = "https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/72x72"
      ICONS = {
          "medal.png": "1f3c5",       # 🏅 score header
          "finger-down.png": "1f447",  # 👇 subhead
          "check.png": "2705",         # ✅ proof pills
      }
      
      
      def main():
          ap = argparse.ArgumentParser()
          ap.add_argument("--run-dir", required=True)
          args = ap.parse_args()
          out = pathlib.Path(args.run_dir) / "assets" / "icons"
          out.mkdir(parents=True, exist_ok=True)
          for name, cp in ICONS.items():
              dst = out / name
              if dst.exists():
                  print(f"[icons] have {name}")
                  continue
              urllib.request.urlretrieve(f"{CDN}/{cp}.png", dst)
              print(f"[icons] {name} <- {cp}.png")
      
      
      if __name__ == "__main__":
          main()
      
  • tests
    • smoke-test.md 686 B
      # Smoke Test
      
      fetch_icons.py --run-dir <run> ; build_overlays.py --config config.json --out-dir <run>/generated/overlays ; compose_master.py --config config.json --run-dir <run> --no-music — deterministic, $0.
      
      Pass when:
      - `fetch_icons.py` lands medal.png / finger-down.png / check.png in `<run>/assets/icons`.
      - `build_overlays.py` emits `01-header-white.png`, `02-header-orange.png`, and one `NN-check-*.png` per proof point into `generated/overlays`.
      - `compose_master.py` produces a valid 1080x1920 `master-final.mp4` with the headers always on and the proof pills revealing in the L->R->L->R cascade.
      - No paid provider call is made (this capability is FREE and deterministic).
      
  • SKILL.md 3.2 KB
    ---
    name: render-proof-points-overlay
    description: Build the deterministic PIL pill overlays for a 'perfect-score + proof-points' UGC video ad (white 10/10 score header with a medal + orange sub with a finger-down + 3-4 green-check proof pills) and composite them onto a base clip in a diagonal L->R->L->R cascade, then mux the music bed into master-final.mp4. Config-driven (config.json), 1080x1920 9:16, FREE and deterministic (no paid calls, text stays pixel-crisp). Use for the overlay-proof-points format; the base clip + music come from separate paid capabilities.
    status: active
    ---
    
    # render-proof-points-overlay
    
    Build the deterministic PIL/FFmpeg overlays for the "Instagram comparison-tool reviewer" UGC ad — a white "we got a perfect 10/10 score" headline pill (trailing medal), an orange "but here's also why you'll love us" sub pill (trailing finger-down, width-matched to the header), and 3-4 green-check proof pills — then composite them onto a base clip in the format's signature diagonal cascade and mux the music into the master. FREE and deterministic: the pills are PIL-rendered so the score, checks, and wordmark stay pixel-crisp (a video model would smear type). The base clip (create-image-fal keyframe -> create-video-fal i2v) and the music bed (create-music-elevenlabs) come from separate paid capabilities; this one only does the free rendering.
    
    ## Run
    fetch_icons.py --run-dir <run> ; build_overlays.py --config config.json --out-dir <run>/generated/overlays ; compose_master.py --config config.json --run-dir <run> — reads <run>/generated/clip-handheld.mp4 + generated/music-bed.m4a, writes <run>/master-final.mp4. 1080x1920, deterministic, $0. (Add --no-music to compose for a silent design preview.)
    
    ## Scripts
    - `fetch_icons.py` — downloads the three Twemoji PNGs (medal 1f3c5, finger-down 1f447, check 2705) to `<run>/assets/icons`. PIL cannot render Apple Color Emoji, so pills paste Twemoji PNGs. Free, local.
    - `build_overlays.py` — PIL: renders the white score header (trailing medal), the orange subhead (trailing finger-down, width-matched to the header), and N green-check proof pills auto-sized to their copy. Bold weight and icon-centered-on-pill-middle are load-bearing.
    - `compose_master.py` — FFmpeg: scale/crop the base clip to 1080x1920@30, composite the always-on headers, cascade the proof pills (each `enable='gte(t,T)'` on its own alternating LEFT/RIGHT row), mux the music, apply the anti-AI grain pass, re-encode crf23/maxrate12M -> master-final.mp4.
    
    ## Contract
    - Deterministic + FREE (PIL + FFmpeg); no paid calls, no AI-rendered text — the score, checks, and wordmark are composited, never generated.
    - Config-driven off one `config.json` (`overlays`, `layout`, `duration_sec`, optional `music`/`post_production`); the template recipe supplies the config from `recipe.config`.
    - Always re-run `build_overlays.py` before `compose_master.py` — the compositor reads pre-rendered PNGs and silently reuses stale ones on a copy change.
    - Headers stay on 0-duration and must not cover the bottle face; proof pills cascade one-per-beat down the diagonal (NOT four-corners) — the cascade is the format's signature.
    - Requires `Pillow` + `ffmpeg`. No API keys.
    
  • skill.meta.json 331 B
    {
      "slug": "render-proof-points-overlay",
      "category": "capabilities",
      "domain": "ads",
      "tags": [
        "ads"
      ],
      "installation": {
        "base_command": "npx goose-skills install render-proof-points-overlay",
        "supports": [
          "claude",
          "cursor",
          "codex"
        ]
      },
      "requires_skills": [
        "watch"
      ]
    }
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related