* fix(cli): validate seeks the runtime player directly, not raw timelines validate's seekTo() only checked for window.__hf.seek (a bridge object the producer's render-pipeline file server injects) before falling back to grabbing window.__timelines and calling .seek() on each raw GSAP timeline directly. validate serves compositions through a plain static file server that never injects that bridge, so this fallback ran on every single validate invocation. Seeking a raw timeline moves the animation state but skips the runtime's own [data-start]/[data-duration] visibility sync (syncMediaForCurrentState in packages/core/src/runtime/init.ts), which is what sets an off-window clip's inline visibility/display styles. Skipping it left elements outside their timeline window looking fully visible to any check that reads computed style afterward at that seek time. This surfaced as validate's WCAG contrast audit (contrast-audit.browser.js) flagging text in off-window clips against whatever background happened to be behind them, since its own visibility filtering trusts the runtime to have already hidden them. Fix: prefer window.__player.renderSeek, which the composition runtime exposes directly on every page load (no bridge required) and which does run the visibility sync, before falling back to the __hf/raw timeline paths. No changes needed to contrast-audit.browser.js itself since its existing visibility check now sees correct computed style. No new test added: seekTo's branch selection runs entirely inside a page.evaluate() callback, which Puppeteer serializes via .toString() for the browser context, so it can't import and call a project-local window.__player stub from a jsdom/vitest test without testing a copy of the logic rather than the shipped code. Verified instead by reading the runtime chain end-to-end: window.__player.renderSeek is always set by packages/core/src/runtime/init.ts's createPlayerApiCompat, calls through to player.renderSeek, which calls syncMediaForCurrentState(). * fix(cli): wait for runtime seek target in validate
hyperframes
CLI for creating, previewing, and rendering HTML video compositions.
Install
npm install -g hyperframes
Or use directly with npx:
npx hyperframes <command>
Requirements: Node.js >= 22, FFmpeg
Commands
init
Scaffold a new Hyperframes project from a template:
npx hyperframes init my-video
cd my-video
preview
Start the live preview studio in your browser:
npx hyperframes preview
# Studio running at http://localhost:3002
npx hyperframes preview --port 4567
render
Render a composition to MP4:
npx hyperframes render ./my-composition.html -o output.mp4
lint
Validate your Hyperframes HTML:
npx hyperframes lint ./my-composition
npx hyperframes lint ./my-composition --json # JSON output for CI/tooling
npx hyperframes lint ./my-composition --verbose # Include info-level findings
By default only errors and warnings are shown. Use --verbose to also display informational findings (e.g., external script dependency notices). Use --json for machine-readable output with errorCount, warningCount, infoCount, and a findings array.
compositions
List compositions found in the current project:
npx hyperframes compositions
benchmark
Run rendering benchmarks:
npx hyperframes benchmark ./my-composition.html
doctor
Check your environment for required dependencies (Chrome, FFmpeg, Node.js):
npx hyperframes doctor
browser
Manage the bundled Chrome/Chromium installation:
npx hyperframes browser
info
Print version and environment info:
npx hyperframes info
docs
Open the documentation in your browser:
npx hyperframes docs
upgrade
Check for updates and show upgrade instructions:
npx hyperframes upgrade
npx hyperframes upgrade --check --json # machine-readable for agents
Documentation
Full documentation: hyperframes.heygen.com/packages/cli
Related packages
@hyperframes/core— types, parsers, frame adapters@hyperframes/engine— rendering engine@hyperframes/producer— render pipeline@hyperframes/studio— composition editor UI