# Lower third — slide bar

Name and role slide in on a frosted bar, hold, then wipe out. Overlay-ready (transparent background). 5 s, 16:9.

- Category: lower-third · Tags: lower-third, caption, interview, overlay
- Spec: 1920×1080 @ 30 fps · 5s (16:9)
- License: CC0 · Tier: free
- JSON: https://gimgs.net/motion/lower-third.json
- Kind: html
- Template HTML: https://gimgs.net/motion/lower-third/template.html
- Player: https://gimgs.net/motion/lower-third/play?p=<base64url JSON params>[&t=<seconds>]
- Credits: gimgs — https://gimgs.net/motion
- Page: https://gimgs.net/motion/lower-third.html

## Params

| name | type | default | description |
|---|---|---|---|
| `name` | string | `"Ada Lovelace"` | Big line (person, place or topic) |
| `role` | string | `"Founder, Analytical Engines"` | Small uppercase line in the accent colour |
| `accent` | string (color) | `"#ffb224"` | Bar and role colour |
| `align` | string · left \| right | `"left"` | Which side of the frame |
| `transparent` | boolean | `false` | true = transparent background for compositing over footage (render PNG frames with alpha, e.g. -c:v prores_ks -pix_fmt yuva444p10le or WebM VP9 with alpha) |
| `holdSeconds` | number | `3.6` | When the out-animation starts (seconds). The clip is always 5 s |

Default params (base64url for `?p=`): `eyJuYW1lIjoiQWRhIExvdmVsYWNlIiwicm9sZSI6IkZvdW5kZXIsIEFuYWx5dGljYWwgRW5naW5lcyIsImFjY2VudCI6IiNmZmIyMjQiLCJhbGlnbiI6ImxlZnQiLCJ0cmFuc3BhcmVudCI6ZmFsc2UsImhvbGRTZWNvbmRzIjozLjZ9`

## Prompt

## When to use
Identify a speaker or a location in interview / documentary / podcast footage. Composite it over the video (set `transparent: true`, render with alpha) or use the built-in dark gradient for a stand-alone caption card.

## How to adapt
- `name` ≤ 24 characters keeps one line at 64px; longer names wrap.
- `align: "right"` mirrors the whole layout for right-side framing.
- `holdSeconds` controls how long the card stays before wiping out; the file is fixed at 5 s so cut the tail if you need it shorter.
- Timeline: bar 0–0.5 s, box wipe 0.25–0.85 s, name 0.55–1.05 s, role 0.75–1.25 s, out from `holdSeconds` for 0.4 s.

## Compositing
Render PNG frames with `--default-background-color=00000000` (Chromium) or `omitBackground: true` (Playwright) when `transparent` is true, then `ffmpeg -framerate 30 -i frame-%04d.png -c:v prores_ks -pix_fmt yuva444p10le lower-third.mov`.

## Do not change
`window.motion`, `#stage` size, `animation-fill-mode: both`.

## Flow

1. **Set params**
   name, role, accent; transparent=true for overlays.
2. **Render with alpha**
   `playwright: page.screenshot({ omitBackground: true }) per frame → ffmpeg -framerate 30 -i frame-%04d.png -c:v prores_ks -pix_fmt yuva444p10le out.mov`
3. **Composite**
   `ffmpeg -i footage.mp4 -i out.mov -filter_complex overlay=0:0:enable='between(t,2,7)' final.mp4`

## Render

Open frame_url in a headless browser with viewport width×height (deviceScaleFactor 1), wait for document.documentElement.dataset.motionReady === '1', screenshot; repeat for t = i/fps (i = 0…frames-1); then `ffmpeg -framerate <fps> -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4`. Or drop ?t to play it live.

## Contract

Self-contained HTML. Declares window.motion = { width, height, fps, duration, params, apply(params) [, seek(t)] }; root element #stage sized width×height; animations are CSS/WAAPI with animation-fill-mode: both so any t can be seeked via document.getAnimations(). The host runtime (injected by /play) merges ?p params, calls apply(), scales #stage to the viewport and, when ?t is given, pauses and seeks deterministically.
