Skip to content

feat(browser-export): 100% client-side MP4/WebM export via WebCodecs (mediabunny)#1905

Open
HackingCorp wants to merge 1 commit into
heygen-com:mainfrom
HackingCorp:feat/browser-export
Open

feat(browser-export): 100% client-side MP4/WebM export via WebCodecs (mediabunny)#1905
HackingCorp wants to merge 1 commit into
heygen-com:mainfrom
HackingCorp:feat/browser-export

Conversation

@HackingCorp

Copy link
Copy Markdown

Summary

Implements the browser-side export path discussed in #1661: a new @hyperframes/browser-export package that renders a live composition to MP4/WebM entirely in the browser — no server, no FFmpeg, no headless Chrome. It complements @hyperframes/producer (which remains the reference for deterministic, pixel-perfect renders); the target is browser-based editors, template SaaS frontends, and quick exports delivered straight to the user's Downloads folder.

Pairs naturally with @hyperframes/lint/browser (#1749/#1773) for a fully client-side validate → render loop.

How it works

  1. Plan — locate the composition root ([data-composition-id] or #root), read dimensions, resolve duration from the master GSAP timeline in window.__timelines (or options.duration).
  2. Audio — parse <audio>/<video> clip metadata (data-start, data-duration/data-end, data-media-start, data-volume — the producer's contract), decode and mix offline with OfflineAudioContext.
  3. Video — per frame: pause + seek every registered timeline at the quantized frame time (Math.round(t·fps)/fps, the producer's parity contract), await <video> layer seeks, rasterize the root to a canvas via SVG foreignObject (html-to-image, fonts embedded once).
  4. Encode — WebCodecs via mediabunny (avc+aac in MP4, vp9+opus in WebM), finalized into a downloadable Blob. Abortable via AbortSignal, per-phase onProgress.

Package shape

  • Single browser entry; tsup platform: "browser" build — the same compile-time node-free guarantee as @hyperframes/lint/browser.
  • Deps: mediabunny (already used by studio's mediaProbe) + html-to-image.
  • Limitations documented in the README/docs page: WebCodecs support matrix, CORS requirements for foreignObject rasterization, async <video> frame alignment with a 500 ms guard, main-thread rendering.

Testing

  • 26 unit tests on the pure logic (composition discovery, clip parsing, frame timing/quantization, deterministic timeline seeks, codec mapping, filenames) — the browser-only modules (OfflineAudioContext / WebCodecs / canvas) are isolated behind small seams.
  • Typecheck clean; browser build + d.ts generation verified; docs page registered in docs.json and the root build order.

🤖 Generated with Claude Code

https://claude.ai/code/session_018TXJXMe4QmSBnmYoR3brtk

…(mediabunny)

New @hyperframes/browser-export package (discussion in heygen-com#1661):
deterministic quantized GSAP seeks (producer parity contract), SVG
foreignObject rasterization (html-to-image), OfflineAudioContext mix of
data-start/data-duration audio clips, WebCodecs encoding via mediabunny
(avc+aac MP4, vp9+opus WebM). Browser-only tsup build (platform:
"browser" compile-time guarantee), 26 unit tests on the pure logic,
docs page + build-order registration.
HackingCorp added a commit to HackingCorp/ltc-motion that referenced this pull request Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant