diff --git a/.github/skills/overview-video/SKILL.md b/.github/skills/overview-video/SKILL.md new file mode 100644 index 0000000..b05ab56 --- /dev/null +++ b/.github/skills/overview-video/SKILL.md @@ -0,0 +1,135 @@ +--- +name: overview-video +description: Rebuild or update the course overview video (about 98 seconds) for this course in videos/overview. Use when running /overview-video, or when asked to refresh the course overview video, add a chapter or feature to it, retake its dark-mode app screenshots, change its copy or timing, add music, or render a new MP4. +--- + +# Course Overview Video + +The project in `videos/overview` makes a 1920x1080 overview video of about 98 seconds +for the course. It is a HyperFrames project (HTML + GSAP, rendered to MP4). +`video.config.json` controls all of the copy, timing, and screenshots. +`scripts/build.mjs` generates `index.html` from it. Never edit `index.html` +by hand. + +Read `videos/overview/README.md` for the file map and scene list, and +`videos/overview/frame.md` for the design system. + +## Requirements + +- Node.js 22+, ffmpeg and ffprobe, and ImageMagick (`magick`). +- HyperFrames runs with `npx --yes hyperframes@0.8.134`. You do not install it. +- For new screenshots: macOS, the signed-in `demo` persona, and the + [`github-copilot-app-automation`](../github-copilot-app-automation/SKILL.md) + skill. + +## Workflow + +Work from `videos/overview`. + +1. **Decide the change.** Read the course `README.md` and the chapter READMEs + to find what changed (new chapter, renamed feature, new app UI). Keep the + total near 90–100 s: when you add time in one place, remove it from + another. Keep + durations on a 0.5 s grid. Think like a beginner: give each chapter at + least 5.5 s and each screen at least 3 s, and cut content before you + shorten them. +2. **Update `video.config.json`.** + - A chapter needs `num`, `short` (tracklist label), `studio` (the chapter's + "From the Studio" name), `headline` (two lines of about 17 characters + or fewer, the second is shown in the gradient), `sub` (one plain line), + `duration`, and either `shots` or `canvas`. + - Headlines name the app feature (for example, "Put it on repeat / with + automations."). Use the studio analogy only in `studio` labels. Do not + use jargon such as "worktree" or "MCP" without a plain `sub` line. + - A shot is `{ "src": "", "focus": [left, top, right, bottom] }` in + 1920x1080 screenshot pixels. The camera pushes in to the focus box. + A focus ring is drawn when the box is small. Use `"ring": false` to hide + the ring, or `"ring": [l, t, r, b]` to draw it on another box. Use + `"fallback": ""` when a shot can be missing. + - Several shots in one chapter share its duration and change by crossfade. + Use no more than three shots in one chapter. A shot can set its own + `"duration"`. + - A shot can play a screen recording: add `"video": "assets/clips/.mp4"` + (1920x1080, H.264, no audio). `src` is the still that shows when the clip + is missing. Optional: `"mediaStart"` (seconds to skip) and `"rate"`. + - `"moves": [{ "at": 1.5, "focus": [l, t, r, b], "dur": 1.2 }]` replaces the + default push with timed camera moves (`at` is seconds into the shot). + Use it to follow the action in a video shot. + Use `steps` with a `step` index on each shot to light a step rail. + - `float` adds mono pills near the card (for example, mode names). Use it + only when it helps a beginner read the screen. +3. **Retake screenshots when the app UI changes.** Follow the + `github-copilot-app-automation` skill with these rules: + - Run the persona on the laptop screen: export + `COPILOT_CAPTURE_DISPLAY=builtin` in every command that runs + `prepare-persona.sh` or `capture-window.sh`. + - Switch the persona to a dark theme in **Settings > Themes** before you + capture, and set the original theme again when you finish. + - Do not add `--callout`, `--box`, `--arrow`, or `--crop`. Video cards must + be clean. + - Save to `videos/overview/assets/shots/.png` (the script also + writes `.webp`). Only the WebP files are committed. + - Do not set `TMPDIR` to a folder in the repository. + - Agent-at-work shots (`session-plan`, `session-working`, + `session-diff-live`, `browser-preview`) need a real session in the + persona. Get the user's approval before you send a prompt. Use a new + worktree and Plan mode. Do not push, open a PR, or merge. Archive the + session when you finish. + - Find focus boxes from a half-size preview of each shot, then double the + coordinates. + - Screen recordings are not sanitized. Hide the sidebar while you record, + check frames every 0.5 s for names, handles, and paths, and cover any + that show. +4. **Build and check.** + ```bash + npm run check + ``` + Lint must report 0 errors, and check must pass. The structure warnings + (`nested_structure_needs_subcomposition`, `timeline_track_too_dense`) are + expected for this generated, single-file composition. If + `composition_heavy_overlay_count_high` shows, remove blur, radial-gradient, + or clip-path elements until it goes away. Otherwise, the render can show + black frames. +5. **Inspect frames.** + ```bash + npm run snapshot + ``` + Open `snapshots/contact-sheet-*.jpg`. Check every headline at its settled + time with `--zoom "# .ch-head"` (and the hook, studio, lockup, and end + titles): no letter may be cut off at the edges or below the baseline + (`?`, `g`, `s`, and `y` are the usual problems). Also take snapshots 0.1 s before and + 0.2 s after each cut that you changed (`npx --yes hyperframes@0.8.134 + snapshot --no-end --at ...`). Look for tight word spacing, text that + overflows, empty frames, and cluttered card crossovers. +6. **Preview, then render.** Run `npm run dev` for Studio. Render only after + the user approves: + ```bash + npm run render # renders/video.mp4 + npm run music -- path/to/track.mp3 --start 8 # renders/video-with-music.mp4 + ``` +7. **Music.** When a track is longer than the video, find its tempo and + beat phase and its big hits and quiet parts (for example, with numpy + on a mono decode). Then set `music.segments` so beats land on the 0.5 s + cut grid and the big hits land on key cuts: the reveal, Chapter 07, and the + end card. Make each edit on a downbeat in a section of similar loudness. + Check the result: the level change at each edit should be within normal + beat-to-beat change, and the loudness about -14 LUFS. +8. **Export.** Run `npm run export` to replace the committed web copy at + `videos/copilot-app-for-beginners-overview.mp4`. Keep it under 50 MB + (GitHub warns above that; the repo does not use Git LFS). +9. **Report** the MP4 paths, the final duration, and any shot that used a + fallback (`build.mjs` prints a warning for each). + +## Rules + +- Keep every visual in the video's own dark style. Do not drop in the + course's cartoon illustrations; they look out of place. +- Keep the copy short and true to the course. Do not claim features that the + chapters do not teach. +- Keep motion professional: no `back`, `elastic`, or bounce eases, and no + infinite loops. +- Keep timing deterministic: no `Math.random`, clocks, or network data at + render time (the build uses a seeded random generator). +- Screenshots must come from the sanitized persona. Before you commit, check + each one for private names, paths, or tokens. +- `renders/` and `snapshots/` are not committed. diff --git a/videos/copilot-app-for-beginners-overview.mp4 b/videos/copilot-app-for-beginners-overview.mp4 new file mode 100644 index 0000000..857ffd4 Binary files /dev/null and b/videos/copilot-app-for-beginners-overview.mp4 differ diff --git a/videos/overview/.gitignore b/videos/overview/.gitignore new file mode 100644 index 0000000..8428685 --- /dev/null +++ b/videos/overview/.gitignore @@ -0,0 +1,6 @@ +renders/ +snapshots/ +node_modules/ +.hyperframes/ +# Capture source PNGs are large. The lossless WebP copies are committed. +assets/shots/*.png diff --git a/videos/overview/.media/preferences.json b/videos/overview/.media/preferences.json new file mode 100644 index 0000000..b65f192 --- /dev/null +++ b/videos/overview/.media/preferences.json @@ -0,0 +1,41 @@ +{ + "version": 1, + "preferences": { + "destination": { + "value": "youtube", + "confirmed_in": [ + "overview" + ], + "updated_at": "2026-10-05T22:53:06.819Z" + }, + "aspect": { + "value": "1920x1080", + "confirmed_in": [ + "overview" + ], + "updated_at": "2026-10-05T22:53:06.858Z" + }, + "language": { + "value": "en", + "confirmed_in": [ + "overview" + ], + "updated_at": "2026-10-05T22:53:06.907Z" + }, + "flow": { + "value": "automation", + "confirmed_in": [ + "overview" + ], + "updated_at": "2026-10-05T22:53:06.952Z" + }, + "storyboard": { + "value": "no", + "confirmed_in": [ + "overview" + ], + "updated_at": "2026-10-05T22:53:06.993Z" + } + }, + "sightings": {} +} diff --git a/videos/overview/AGENTS.md b/videos/overview/AGENTS.md new file mode 100644 index 0000000..ebeaa3e --- /dev/null +++ b/videos/overview/AGENTS.md @@ -0,0 +1,113 @@ +# Course overview video + +This project is generated. Edit `video.config.json`, `src/`, or `scripts/`, +then run `npm run build`. Follow the repo skill +`.github/skills/overview-video/SKILL.md` for the full workflow. + +# HyperFrames Composition Project + +## Skills — USE THESE FIRST + +**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions. + +**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), confirms your brief up front (the intent layer), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to: + +- `/product-launch-video` — any **website** URL or brief / script → a product launch / SaaS / promo video, or a site tour / showcase featuring the site's own captured visuals. +- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer. +- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched. +- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.) +- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor). +- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`. +- `/music-to-video` — a **music track** (audio file, video to pull audio from, or one generated from a mood brief) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid. +- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video. +- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition) and the home of **companion mode** — co-create with the full HyperFrames toolbox; the original hyperframes authoring flow, any length. + +**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above. + +The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-audio`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent. + +**Changing how real footage or images look or reveal?** Load `/media-use` and read its `references/media-treatments.md` before editing, even when the request only says dark, flat, boring, retro, private, or “make the reveal cooler.” It governs how footage is treated, never whether media may be used. Use canonical media treatments and seek-safe motion; do not improvise equivalent CSS/SVG filters or overlays. + +> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`. + +> **Using a HyperFrames plugin?** Load skills from that installed bundle and follow +> its `hyperframes/references/plugin-installation.md` execution rules. Update via +> the plugin manager, not the standalone commands below. +> +> **Standalone skill missing or stale?** Run `npx hyperframes skills update ` to install/refresh +> the specific skill you need (the `/hyperframes` router does this automatically before +> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus +> everything already installed — neither pulls the full set. Restart the agent session so +> newly installed skills load. + +## Commands + +```bash +npm run dev # human-operated foreground preview (blocks until stopped) +npx hyperframes preview --background # agent-safe persistent Studio preview +npx hyperframes preview --status # verify the persistent preview is listening +npx hyperframes preview --stop # stop it when review is finished +npm run check # lint + runtime + layout + motion + contrast (one command) +npm run render # render to MP4 +npm run publish # publish and get a shareable link +npx hyperframes lint --verbose # include info-level findings +npx hyperframes lint --json # machine-readable output for CI +npx hyperframes docs # reference docs in terminal +``` + +> **Agents must use `npx hyperframes preview --background` for Studio handoff.** Do not rely +> on a shell/tool `run_in_background` wrapper around `npm run dev`: that foreground process +> remains owned by the invoking session and can disappear while the browser stays open, +> leaving refreshes at `ERR_CONNECTION_TIMED_OUT`. Verify with `preview --status`, keep it +> alive through review, and stop it explicitly with `preview --stop` afterward. + +> **Pinned CLI version.** These scripts pin an exact `hyperframes@X.Y.Z` so this project re-renders identically over time. Weeks later that pin lags fixes shipped since. To move up: `npx hyperframes@latest upgrade --project . --check` (shows the delta), then `npx hyperframes@latest upgrade --project .` to rewrite the pins. Always unpinned — the pinned script re-runs the old version against itself. + +## Documentation + +**For quick reference**, use the local CLI docs command (no network required): + +```bash +npx hyperframes docs +``` + +Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting` + +**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs: + +``` +https://hyperframes.heygen.com/llms.txt +``` + +## Project Structure + +- `index.html` — main composition (root timeline) +- `compositions/` — sub-compositions referenced via `data-composition-src` +- `meta.json` — project metadata (id, name) +- `transcript.json` — whisper word-level transcript (if generated) + +## Linting — ALWAYS RUN AFTER CHANGES + +After creating or editing any `.html` composition, **always** run the full check before considering the task complete: + +```bash +npm run check +``` + +Fix all errors before presenting the result. Warnings should be reviewed before rendering. + +## Key Rules + +1. Every timed element needs `data-start` and a duration. `data-start` is what marks it as timed; `data-track-index` is an optional Studio display lane the render never reads +2. Give timed visual elements `class="clip"`. The framework keys visibility off `data-start`, not the class, but the shared `.clip` CSS is what gives a scene its full-frame box, and `lint` warns without it +3. Register one paused root timeline per composition on `window.__timelines`: + ```js + window.__timelines = window.__timelines || {}; + window.__timelines["composition-id"] = gsap.timeline({ paused: true }); + ``` + Scene timelines manually added to this root must not be paused. A paused + child does not advance when the root is seeked. The runtime activates + registered composition siblings, not arbitrary nested scene timelines. +4. A video with sound keeps it on the `