mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-15 13:58:20 +00:00
A composition mounted as a sub-composition lost its entire stylesheet and scripts whenever they were authored as siblings of the composition root inside its template. mountCompositionContent collected assets from the composition root element, so sibling nodes were invisible to it. The shape is legal and common, so the result was three catalog components rendering completely unstyled in live preview. oversized-cursor drew its pointer at 1280px against an authored 7cqw, roughly 134px at 1920, because width: 7cqw was never declared at all -- the whole stylesheet was missing. Confirmed in the mounted document, where only the host's own style element was present. Collect from the source node, which is a superset of the root and the single point every mount path routes through: external fetch, inline template, nested. Strip the mounted clone rather than the source. The previous code removed the extracted nodes from the node it was given, which on the inline-template path is a live template still in the document -- a remount would have found it emptied. Why nothing caught it: every CLI gate reaches the compiler path through bundleToSingleHtml, and the compiler always collected from the whole template. Nothing in the CLI exercises the mount path, which is reachable only through the player and Studio. So the rendered video was correct the entire time and only the preview was wrong. A test spanning both paths lands separately. The regression test fails on the pre-fix code, asserting that the mounted document contains the composition's own container-type declaration and finding an empty string instead -- the stylesheet that never arrived -- and passes after. Verified in both directions rather than assumed.
@hyperframes/core
Types, parsers, generators, compiler, linter, runtime, and frame adapters for the Hyperframes video framework.
Install
npm install @hyperframes/core
Most users don't need to install core directly — the CLI, producer, and studio packages depend on it internally.
What's inside
| Module | Description |
|---|---|
| Types | TimelineElement, CompositionSpec, Asset, canvas dimensions, defaults |
| Parsers | parseHtml — extract timeline elements from HTML; parseGsapScript — parse GSAP animations |
| Generators | generateHyperframesHtml — produce valid Hyperframes HTML from a composition spec |
| Compiler | compileTimingAttrs — resolve data-start / data-duration into absolute times |
| Linter | lintHyperframeHtml — validate Hyperframes HTML (missing attributes, overlapping tracks, etc.) |
| Runtime | IIFE script injected into the browser — manages seek, media playback, and the window.__hf protocol |
| Frame Adapters | Pluggable animation drivers (GSAP, Lottie, CSS, or custom) |
Frame Adapters
A frame adapter tells the engine how to seek your animation to a specific frame:
import { createGSAPFrameAdapter } from "@hyperframes/core";
const adapter = createGSAPFrameAdapter({
getTimeline: () => gsap.timeline(),
compositionId: "my-video",
});
Implement FrameAdapter for custom animation runtimes:
import type { FrameAdapter } from "@hyperframes/core";
const myAdapter: FrameAdapter = {
id: "my-adapter",
getDurationFrames: () => 300,
seekFrame: (frame) => {
/* seek your animation */
},
};
Parsing and generating HTML
import { parseHtml, generateHyperframesHtml } from "@hyperframes/core";
const { elements, metadata } = parseHtml(htmlString);
const html = generateHyperframesHtml(spec);
Linting
import { lintHyperframeHtml } from "@hyperframes/core/lint";
const result = lintHyperframeHtml(htmlString);
// result.findings: { severity, message, elementId }[]
Documentation
Full documentation: hyperframes.heygen.com/packages/core
Related packages
@hyperframes/engine— rendering engine that drives the browser@hyperframes/producer— full render pipeline (capture + encode)hyperframes— CLI