mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-14 21:29:34 +00:00
Both analysis loops allocated a fresh `Float64Array(4096)` pair inside the per-window loop. A 5-minute 48 kHz voiceover is ~7030 windows, so one carve churned ~460 MB of transient Float64Array through the main thread — the panel's thread — for a measurement that needs 64 KiB of scratch. Now one pair is reused; `re` is fully overwritten each window and only `im` has to be cleared. Wall-clock is unchanged (591 ms vs 596 ms on that file, within noise): the FFT dominates and a bump allocation is nearly free. This is a GC-pressure fix, not a latency one, and the band values it produces are bit-identical. The review's third loop is `analyseCarveDuck`, which runs `windowDb` rather than an FFT and allocates nothing per window — nothing to fix there. Striding the Welch hops was tried and REJECTED. It is 27x faster on a 5-minute voiceover (427 ms -> 15 ms), but it moves the result: at strength 0.9 the chosen band set changed (630 Hz became 160 Hz), and it did not converge back to the full read even at 2048 windows. That is the author's carve being silently redrawn to save time on a measurement that already locks the rack while it runs. The reason is recorded in the code so it is not re-attempted. Falsified by deleting `im.fill(0)` from both loops: five tests fail, including the two added here — a steady tone must measure the same bands whatever its length, and its dynamics envelope must sit still rather than sliding as the contamination accumulates. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@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