* fix(cli): hide console windows on Windows for background/detached spawns Add windowsHide: true to 8 spawn/execFile call sites that were missing it: ffprobe/ffmpeg probes in the producer and engine packages, the telemetry exit-flush and studio dev-server spawns, and the browser-open and background-preview detached launches in the CLI. previewLifecycle.ts's spawnDetachedPreview redirects stdout/stderr to a raw log-file descriptor; libuv only adds Windows' CREATE_NO_WINDOW flag when no stdio slot inherits a raw handle, so windowsHide alone does not fully suppress a console flash there (documented inline) — it's still added for consistency and because it correctly sets the process's show-window state regardless. Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com> * fix(cli): correct windowsHide flash-risk claims and add missing dev-server spawn tests - The previewLifecycle.ts comment (and its mirrored test comment) overstated the residual console-flash risk on the detached background preview spawn: DETACHED_PROCESS already leaves that child without a console regardless of whether CREATE_NO_WINDOW gets applied. - Add the two missing regression tests for preview.ts's runDevMode and runLocalStudioMode spawns, exporting both for test access. - Drop an unused export in audioPadTrim.ts flagged by the repo's dead-code gate; the constant is only ever used within its own file. Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com> * fix(engine): hide console window for the drawElement self-verify PSNR comparison psnr.ts's execFile call runs in-process inside the Studio server's render path (parallelCoordinator.ts's drawElement disk self-verify), so a render started from Studio's UI under a detached preview hits this call from a console-less parent — the same flash case the other windowsHide sites in this PR already cover. psnrFilterAvailability.ts's probe is on the same in-process render path and already had the flag. Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com> * fix(cli): keep only the spawn sites main still misses and leave browser windows visible windowsHide maps to libuv UV_PROCESS_WINDOWS_HIDE, which also starts GUI apps with SW_HIDE, so the detached browser launch must not set it. The background preview child already has no console (DETACHED_PROCESS with inherited log fds), so its flag was a no-op. The telemetry, psnr and audioPadTrim sites shipped on main via #3839 and #4604. * fix(cli): stop the studio dev server when the terminal closes With windowsHide the dev server runs in its own hidden console on Windows, so closing the terminal only signals the wrapper (SIGHUP). Handle it like SIGINT and SIGTERM and kill the process tree. * fix(studio-server): hide the console window for loudness measurement The background preview has no console, so its ffmpeg loudness run opened a visible window on Windows. * refactor(cli): drop the comment on the studio shutdown signals --------- Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
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: http://localhost:3002/#project/my-video
# Server: http://localhost:3002
npx hyperframes preview --port 4567
In an interactive terminal, the preview stays attached until you press
Ctrl+C. In a non-interactive shell such as a coding-agent session, the same
command starts a managed preview that survives after the command returns. Use
--background or --foreground to choose explicitly, and manage persistent
previews with --status, --stop, --list, and --kill-all. Add --json to
managed lifecycle commands for machine-readable output. --foreground --json
prints the ready-session envelope once, then remains attached until stopped.
normalize-audio
Measure two local authored audio clips with integrated LUFS and match the target
to the unchanged reference. The command is a dry run unless --write is passed:
npx hyperframes normalize-audio --reference target-audio --target user-audio
npx hyperframes normalize-audio --reference target-audio --target user-audio --write
It updates only the target element's data-volume and refuses unsafe boosts
that exceed Studio's +12 dB ceiling or would clip.
render
Render a composition to MP4. Run from the project directory; the positional
argument is the project directory (not a file), so render the project's
index.html directly, or point at a specific composition file with -c:
npx hyperframes render -o output.mp4
npx hyperframes render -c ./my-composition.html -o output.mp4
Set HYPERFRAMES_RENDER_DETACHED=1 when starting a render with nohup or
disown so it keeps running after the invoking shell exits.
publish
Upload a project directory and get a hosted URL that keeps working after the CLI exits. Published projects are private by default:
npx hyperframes publish
npx hyperframes publish ./my-video
npx hyperframes publish --public
npx hyperframes publish --yes
Signed-out publishing returns an authentication-required claim URL; opening it
lets someone sign in and claim the project. Sign in first with
npx hyperframes auth login to publish an owned project you can update. Use
--public to make the claimed project visible to anyone. --yes only skips the
confirmation prompt and does not change visibility.
Signed-in publishers can use --update <url-or-id> to target an existing project
or --space <space-id> to publish into a shared team space. If the requested
project is missing or inaccessible, publishing can create a new project instead;
check the printed URL and status.
See the publish reference for all options, including video proxy settings.
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