mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-14 13:27:13 +00:00
Bass, middle and treble is the most widely understood audio control there is, which makes it the right answer for an author who would never reach for a parametric filter. It also removes a real failure: without it, a chain shaping two ranges holds two peaking filters that look identical in the rack. Built the way the carve is — one module owning several tagged nodes rather than a new effect type. Three bands ARE a low shelf, a peaking and a high shelf, so there is nothing new in the graph, nothing new in the render, and an author who opens the details finds exactly the filters they could have added by hand. That shape is also forced: the registry's parameters are a flat key/value record, so an `eq` effect TYPE carrying N bands would need array-shaped params it has no way to express. Two band sets. Three is Bass/Middle/Treble. Five opens to Bass/Warmth/Middle/Clarity/Air, named from the shared vocabulary the rest of the rack uses, so reaching for the EQ is also how the words get learned. The chain is authoritative, not a cached band list: an author can open the details and move a frequency by hand, and the faders read it back rather than overwriting it on the next drag. The fader is held to ±12 dB while the filters themselves allow ±40 — a tone control that can bury a track under 40 dB of bass is not a tone control. `fromEq` joins `fromCarve`, `fromPreset` and `label` through the parser and serializer, so an EQ survives the attribute round trip. Without that the module cannot find its own bands after a reload and silently becomes loose filters. Fourteen tests, falsified against four mutations: the parser dropping fromEq, the fader re-seeding the whole band (which would lose a hand-set frequency), the ±12 clamp removed, and two EQs sharing an id. Core 1690 -> 1704. 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