Skip to content

feat(registry): add media treatment overlays#2754

Open
ukimsanov wants to merge 1 commit into
feat/media-treatment-agentfrom
feat/media-treatment-overlays
Open

feat(registry): add media treatment overlays#2754
ukimsanov wants to merge 1 commit into
feat/media-treatment-agentfrom
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 on lines +32 to +39
const { preview } = result;
if (!preview) return c.json({ error: "Registry preview not found" }, 404);
return new Response(new Uint8Array(preview.content), {
headers: {
"Content-Type": preview.contentType,
"Cache-Control": "no-cache",
},
});
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>

@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
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