Skip to content

feat(registry): add media treatment overlays#2754

Merged
ukimsanov merged 1 commit into
mainfrom
feat/media-treatment-overlays
Jul 25, 2026
Merged

feat(registry): add media treatment overlays#2754
ukimsanov merged 1 commit into
mainfrom
feat/media-treatment-overlays

Conversation

@ukimsanov

Copy link
Copy Markdown
Collaborator

What

Adds four editable Registry overlays: Camcorder HUD, Editorial Flash, Freeze-Frame Cutout, and Organic Light Leak. It also adds the read-only local Registry preview route used by Studio cards.

Why

Color and shader effects cannot express timeline dressing such as HUD copy, flashes, cutouts, or light-leak layers. These remain independent deterministic composition layers.

How

Three overlays are HTML/CSS/paused-GSAP components; Organic Light Leak installs one media asset. Local development serves generated preview posters/videos through the existing Studio adapter while published manifests retain CDN URLs.

Test plan

  • Registry component validation: 2/2
  • Registry preview route tests: 3/3
  • Studio-server and Studio typechecks pass
  • Format, lint, tracked-artifact, file-size, and Fallow gates pass
  • Manual render checks verified Camcorder time/REC motion

Draft blocker

The eight new preview CDN URLs currently return 403. The generated previews must be uploaded by a maintainer with the required HeyGen AWS profile before this PR is merge-ready. Installed overlay components themselves work locally.

Stack 4/6. Base: #2753.

@ukimsanov
ukimsanov marked this pull request as ready for review July 24, 2026 03:42
Copilot AI review requested due to automatic review settings July 24, 2026 03:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new “media treatment overlay” Registry components and enables Studio to serve locally-generated preview posters/videos for Registry catalog cards via the Studio server API.

Changes:

  • Added four Registry overlay components (Camcorder HUD, Editorial Flash Overlay, Freeze-Frame Cutout, Organic Light Leak Overlay) including manifests, snippets, demos, and an owned MP4 asset for the light leak.
  • Extended Studio’s adapter + routes to optionally serve local Registry preview media, and updated the Studio Vite adapter to prefer local generated previews when present.
  • Added route-level tests covering success, validation, and adapter failure behavior for Registry preview serving.

Reviewed changes

Copilot reviewed 17 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
registry/registry.json Registers the new overlay components in the top-level Registry catalog list.
registry/components/organic-light-leak-overlay/registry-item.json Defines the component manifest, install targets, tags, and CDN preview metadata.
registry/components/organic-light-leak-overlay/organic-light-leak-overlay.html Provides the installable styling/snippet guidance for the owned light leak asset usage.
registry/components/organic-light-leak-overlay/demo.html Demo composition showing how to drive the overlay via a paused GSAP timeline.
registry/components/freeze-frame-cutout/registry-item.json Defines the component manifest, tags, and preview metadata.
registry/components/freeze-frame-cutout/freeze-frame-cutout.html Provides the overlay HTML/CSS snippet for the freeze-frame cutout look.
registry/components/freeze-frame-cutout/demo.html Demo composition showing the cutout/tape/flash driven via GSAP.
registry/components/editorial-flash-overlay/registry-item.json Defines the component manifest, tags, and preview metadata.
registry/components/editorial-flash-overlay/editorial-flash-overlay.html Provides the static flash overlay layers and CSS-variable customization surface.
registry/components/editorial-flash-overlay/demo.html Demo composition showing a flash-cut transition driven via GSAP.
registry/components/camcorder-hud/registry-item.json Defines the component manifest, tags, and preview metadata.
registry/components/camcorder-hud/demo.html Demo composition embedding the HUD as a sub-composition.
registry/components/camcorder-hud/camcorder-hud.html Installable HUD snippet with a seek-safe counter/REC blink timeline.
packages/studio/vite.adapter.ts Overrides Registry preview URLs to a local /api/registry/previews/... route when generated preview media exists on disk; implements adapter read for preview bytes.
packages/studio-server/src/types.ts Adds optional readRegistryPreview adapter API for preview bytes + content-type.
packages/studio-server/src/routes/registry.ts Adds a GET route to serve local Registry poster/video previews via the adapter.
packages/studio-server/src/routes/registry.test.ts Adds tests for preview serving success, validation errors, missing previews, and adapter failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/studio-server/src/routes/registry.ts Outdated
Comment thread registry/components/editorial-flash-overlay/demo.html Outdated
Comment thread registry/components/freeze-frame-cutout/demo.html Outdated
Comment thread registry/components/organic-light-leak-overlay/demo.html Outdated

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Audited: all four installable component snippets/manifests; Studio Registry route, adapter contract, Vite adapter implementation, route tests, runtime timeline binding/seeking contract, existing reviews, and CI at exact head f02ecc6b.

Trusting: demo visual composition and binary preview/media assets were inspected for integration shape but not pixel-reviewed; generated registry/registry.json ordering was not regenerated independently.

The three static host-driven overlays keep animation ownership explicit, Registry names/kinds are validated before adapter access, and local preview fallback preserves remote manifest URLs when a generated variant is absent. Copilot already covers Range support and the three GSAP version mismatches; I did not repeat them.

Blocker: registry/components/camcorder-hud/camcorder-hud.html:114-148 tells users to paste the HUD inside an existing composition, but creates a separate timeline under the fixed key camcorder-hud. Runtime standalone seeking only seeks a registered timeline when a matching [data-composition-id="camcorder-hud"] exists (packages/core/src/runtime/init.ts:2544-2550). In the advertised installed shape the host has a different ID and already owns its root timeline, so this HUD timeline is not composition-time-seeked; the counter/REC state can stay frozen or advance from wall-clock sibling activation instead of matching scrub/render time. The demo masks the defect by making its root composition ID camcorder-hud. Either make the installed HUD a real subcomposition with a matching ID/timing contract, or attach its tween to the actual host timeline; add a regression using a differently named host composition.

Ponytail: packages/studio-server/src/routes/registry.ts:25-33: shrink: the promise is boxed into { preview } only to distinguish rejection from a legitimate null. A direct try/catch around await adapter.readRegistryPreview(...) plus the existing null check is clearer. net: -3 lines possible.

— Magi

Verdict: REQUEST CHANGES
Reasoning: The installed Camcorder HUD violates the runtime timeline key contract in its documented usage shape, and the self-contained demo does not exercise that shape.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additive review at f02ecc6b. @magi has CHANGES_REQUESTED (the Camcorder HUD timeline-seek gap) and @Copilot commented (preview Range handling; gsap@3.15.0 vs 3.14.2 in the demo files). Layering my render/registry angle; not repeating those.

Concur with @magi's blocker — and I verified the blast radius is Camcorder HUD only. Magi's finding is right: camcorder-hud.html reads the host's composition id (var host = hud.closest("[data-composition-id]"), :122) but registers its paused timeline under the fixed key window.__timelines["camcorder-hud"] (:148). The runtime composition-seeks a registered timeline only when a matching data-composition-id exists, so the demo (whose root id is literally camcorder-hud) masks it; installed under a normally-named host the REC/counter timeline is never deterministically seeked → frozen or timing-dependent in capture. Additive scoping: I grepped the other three installed overlays — editorial-flash-overlay, freeze-frame-cutout, organic-light-leak-overlay register zero __timelines entries; each documents that the host's paused timeline owns its opacity/reveal, so they ride the host seek and are seek-safe. So Magi's fix is confined to Camcorder HUD, and the host-owned pattern the other three use is the correct one to mirror (register under the host's actual composition id, or drive the HUD from the host timeline) — plus the differently-named-host regression Magi asks for.

Good (verified): the preview route's path-safety is solid — registry.ts:22 rejects any itemName not matching ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$ before the adapter touches disk, so ../ traversal can't reach readRegistryPreview's join(previewRoot, subdir, itemName + ext). Installed components pin the correct gsap@3.14.2 (the 3.15.0 drift Copilot flagged is demo-only). The four overlays are genuinely orthogonal to the #2751/#2752 color-grading contract (HUD copy / flash / cutout / light-leak are DOM dressing, not shader effects) — no contract duplication.

Nits (mine):

  • vite.adapter.ts recomputes resolve(__dirname, "../../docs/images/catalog") and iterates ["blocks", "components"] in both listRegistryCatalog and readRegistryPreview — worth a shared const so the preview root + subdir list have one owner.
  • readRegistryPreview leans entirely on the route's slug regex for path-safety and doesn't re-validate itemName itself. Fine for the dev-only Studio server today, but a defense-in-depth guard in the adapter would keep it safe if a second (non-route) caller ever appears.

Merge gate: the PR's own draft blocker — the 8 preview CDN URLs returning 403 until a maintainer with the HeyGen AWS profile uploads the generated previews — is the real pre-merge item, independent of the code review.

Verdict: COMMENT — I concur with @magi's CHANGES_REQUESTED (verified + scoped to Camcorder HUD); the CDN-upload draft blocker gates merge regardless. (Deferring any stamp to the maintainer.)

Review by Jerrai (hyperframes)

@ukimsanov
ukimsanov force-pushed the feat/media-treatment-agent branch from d91c2f4 to a96419f Compare July 24, 2026 06:30
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from f02ecc6 to 6b7bb56 Compare July 24, 2026 06:30
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-agent branch from a96419f to d0d9c38 Compare July 24, 2026 15:21
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from 6b7bb56 to 9b79f5b Compare July 24, 2026 15:36
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-agent branch from d0d9c38 to ba10d66 Compare July 24, 2026 16:06
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from 9b79f5b to 1a12cf4 Compare July 24, 2026 16:08

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review at 1a12cf41. @magi re-reviewing in parallel; independent verdict.

Magi's camcorder-hud blocker is resolved. The overlay (now registry/blocks/camcorder-hud/camcorder-hud.html) reads the host's data-composition-id at runtime, guards a missing host (:131 throws a clear error), and registers a paused seek-driven timeline under that dynamic compositionId (:160) — no more fixed __timelines["camcorder-hud"] key. The registration key now always matches the seek lookup, so it's deterministic on any host, not just the demo. gsap pinned to 3.14.2.

The CDN-preview draft-blocker is resolved by removal. The /registry/previews/:name/:kind studio-server route was deleted (route + tests + adapter type together), and the overlays moved to registry/blocks/ with local demo.html + backdrop assets — so nothing depends on the 8 CDN preview URLs that were 403'ing.

The restructure is clean. components/blocks/ (and freeze-frame-cutoutfreeze-frame-dressing): registry.json registers all four under the new paths, no dangling components/ paths or old names remain in the registry, and CI is CLEAN at 1a12cf41.

important — the freeze-frame-cutoutfreeze-frame-dressing rename is incomplete in two references:

  • skills/media-use/references/media-treatment-recipes.md:829npx hyperframes add freeze-frame-cutout --no-clipboard still uses the old name; post-merge that add fails (no block by that name). Functional — a loud failure, not silent.
  • docs/guides/color-grading.mdx:325 — still names the freeze-frame-cutout block (cosmetic).
    Update both to freeze-frame-dressing so the rename is complete.

Verdict: COMMENT — ready on the merits; Magi's blocker and the CDN issue are resolved and the restructure is clean. The only open item is the two dangling freeze-frame-cutout references above (important, but not blocking — loud failure). Deferring the stamp; happy to APPROVE on @jrusso1020's go.

Review by Jerrai (hyperframes)

miguel-heygen
miguel-heygen previously approved these changes Jul 24, 2026

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Audited: exact head 1a12cf41; all four installable overlay blocks/manifests and demos; Camcorder HUD composition ownership and bundling regression; Registry catalog updates; preview-generation routing; all eight published poster/video URLs; current reviews/threads; and exact-head checks.

Trusting: preview visuals were not pixel-reviewed frame by frame; generated catalog ordering was inspected rather than regenerated locally; the focused registry bundling regression is covered by exact-head CI rather than a separate local dependency install.

My prior blocker is fully resolved. Camcorder HUD is now a real data-composition-id="camcorder-hud" composition with a dynamically keyed paused timeline, while its demo uses a differently named camcorder-hud-demo host and embeds the HUD via data-composition-src. The bundling regression verifies the differently named host survives and the inlined subcomposition registers under camcorder-hud, matching runtime seek semantics.

The prior publish gate is also cleared: all four poster URLs and all four MP4 URLs return HTTP 200. The old Studio Range and demo GSAP comments are outdated because that route delta was removed and current demos pin GSAP 3.14.2. Exact-head checks are green. No new correctness, registry-contract, render-seam, duplication, or unnecessary-complexity blocker found.

— Magi

Verdict: APPROVE
Reasoning: The HUD now obeys the runtime subcomposition/timeline contract with a differently named-host regression, published previews are live, and exact-head CI is green.

@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from 1a12cf4 to 32918fc Compare July 24, 2026 16:54
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-agent branch from ba10d66 to e65276f Compare July 24, 2026 18:18
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from 32918fc to 7ae3dea Compare July 24, 2026 18:19
jrusso1020
jrusso1020 previously approved these changes Jul 24, 2026

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE at 7ae3dea6 per @jrusso1020's go. Re-verified since my COMMENT at 1a12cf41:

  • My one open finding is fixed. The freeze-frame-cutoutfreeze-frame-dressing rename is now complete — git grep freeze-frame-cutout is empty across docs + skills, and the two dangling refs I flagged are corrected: docs/guides/color-grading.mdx (block name) and skills/media-use/references/media-treatment-recipes.md (npx hyperframes add freeze-frame-dressing, which would have failed post-merge under the old name).
  • The registry/overlay content I reviewed is unchanged — the camcorder-hud blocker resolution (timeline registered under the host's runtime data-composition-id, with a null-host guard) still holds; the delta since 1a12cf41 is docs + base-movement only (the merged #2752 init.ts visibility fix and other merged PRs' proxyTranscoder/preview churn), not this PR's own overlay code.
  • Full required suite green at this head; @magi also approved.

(Note: this is currently stacked on #2753's branch; if #2753 merges and this retargets onto main, I'll re-confirm the rebased head.)

Review by Jerrai (hyperframes)

@ukimsanov
ukimsanov force-pushed the feat/media-treatment-agent branch from e65276f to 4582881 Compare July 25, 2026 01:43
@ukimsanov
ukimsanov force-pushed the feat/media-treatment-overlays branch from 7ae3dea to b0d3164 Compare July 25, 2026 01:43
Base automatically changed from feat/media-treatment-agent to main July 25, 2026 02:33
@ukimsanov
ukimsanov dismissed stale reviews from jrusso1020 and miguel-heygen July 25, 2026 02:33

The base branch was changed.

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE re-stamp at b0d3164d per @jrusso1020's standing go for this batch (my approval at 7ae3dea6 was auto-dismissed when #2753 merged and this retargeted onto main — the predicted stacked-PR dismissal, third instance in this stack). Re-verified against the same three gates:

1. The head actually moved. 7ae3dea6b0d3164d, base e65276f14582881d. #2753 merged as a merge-commit (3978b8e8), and I confirmed 4582881d is now an ancestor of main, so this PR's parent content is genuinely upstream rather than still-pending stack state.

2. The PR's own content is byte-equivalent to what I approved. Three-dot own delta at each head: identical 23-file sets, 22 of 23 blob-identical. The one drift is skills-manifest.json, and here the proof is even tighter than on #2753 — this PR's own manifest delta is literally identical at both heads (media-use: 1234dcf9…470beb65…, same from and same to). The blob differs only because the inherited baseline moved: #2753's rebased manifest carried main's hyperframes-cli re-baseline (from the merged #2765 lint-rule removal). So the same PR-authored change applied on top of a newer base. Skills: manifest in sync is green, which is CI's regen confirmation.

Spot-checked that the substantive prior fixes survived rather than trusting the blob math alone: registry/blocks/camcorder-hud/camcorder-hud.html is blob-identical (f5bb2d02) and still resolves its host dynamically — closest("[data-composition-id]") at :130, hard failure at :132 if absent, timeline registered under the runtime compositionId at :160, not the old fixed key. And my one open finding from the last round stays closed: git grep freeze-frame-cutout at this head returns zero dangling refs.

3. CI is green at the approved head. 38 success, 0 failures, zero non-success check-runs. regression-shards reports skipped, and that is the path filter working as intended, not a bypassed gate: this PR touches no render-path code at all (registry blocks, registry.json, docs, one CLI registry test, a catalog-preview script, skills — nothing under packages/{core,engine,producer,player}), the aggregate required regression gate passes, and the identical skip profile was present at 7ae3dea6, the head I already approved through. Strictly more checks ran here (45 vs 13) after the retarget onto main.

Verdict: APPROVE
Reasoning: Clean retarget onto main with byte-equivalent own content, the single manifest diff is the identical PR-authored change on a moved baseline, both prior blockers verified still fixed at this head, and every required check is green.

Review by Jerrai (hyperframes)

@ukimsanov
ukimsanov merged commit 359a13f into main Jul 25, 2026
45 checks passed
@ukimsanov
ukimsanov deleted the feat/media-treatment-overlays branch July 25, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants