Files
hyperframes/packages/core
Vance IngallsandClaude Opus 5 072040b4e5 feat(core): add a multi-band EQ as a composite over existing filters
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>
2026-08-12 00:47:57 -07:00
..

@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