fix(player,studio): resolve root timeline from DOM instead of last key - #247
Merged
Merged
Conversation
Bundled previews register a master composition alongside its sub-compositions
in `window.__timelines`, e.g. { main, intro, scene2, scene5 }. Both the
player's probe and studio's getAdapter() were using `keys[keys.length - 1]`
to pick the adapter, which returned whichever timeline was registered last.
That made the player report the final sub-composition's duration as the
video length (e.g. 3.2s instead of the master's 14s) and play/pause/seek
targeted that sub-composition instead of the full composition.
Look up the outermost `[data-composition-id]` element in the iframe DOM
and use its id to select the right timeline. Falls back to last-key when
no element is present (standalone sub-composition previews) so drill-down
views keep working.
Also restores `main`/`import` entry points on @hyperframes/player to
point at compiled dist output (the src/ paths broke workspace consumers
that only receive the published tarball).
3 tasks
miguel-heygen
added a commit
that referenced
this pull request
Apr 13, 2026
Ships the root-timeline resolution fix (#247), the SSR-safe player load, and the captions import cleanup.
miguel-heygen
added a commit
that referenced
this pull request
Apr 13, 2026
* fix(studio): load @hyperframes/player lazily to support SSR Player.tsx had a bare `import "@hyperframes/player"` at module scope. The player package registers a class that extends HTMLElement as a side effect, and HTMLElement doesn't exist in a Node server runtime. Any consumer that imported from @hyperframes/studio during server-side rendering (e.g. the Next.js App Router evaluating a client component for SSR) threw `HTMLElement is not defined`. Move the import inside the mount effect via dynamic `import(...)` so it only runs in the browser, and wire up a cancellation flag and deferred cleanup so a fast unmount doesn't leak listeners or DOM nodes. * fix(studio): remove .js extensions from captions-internal imports The captions module imported sibling files as `./types.js` and `./parser.js`. That's legal ESM TypeScript, but Turbopack (and other bundlers) refuse to resolve those specifiers against .ts files when the package is consumed from node_modules — the rest of @hyperframes/studio uses extensionless imports for that reason. Align captions with the rest of the codebase so the package builds without bundler-specific configuration in consumers. * chore: release @hyperframes/[email protected] and @hyperframes/[email protected] Ships the root-timeline resolution fix (#247), the SSR-safe player load, and the captions import cleanup.
miguel-heygen
added a commit
that referenced
this pull request
Apr 13, 2026
Coordinated minor bump across all published packages: - @hyperframes/cli 0.2.5 → 0.3.0 - @hyperframes/core 0.2.5 → 0.3.0 - @hyperframes/engine 0.2.5 → 0.3.0 - @hyperframes/player 0.2.7 → 0.3.0 - @hyperframes/producer 0.2.5 → 0.3.0 - @hyperframes/studio 0.2.9 → 0.3.0 Carries the two studio fixes in this PR (SSR-safe player load, captions-internal imports) plus the DOM-based root timeline resolution from #247.
miguel-heygen
added a commit
that referenced
this pull request
Apr 13, 2026
Coordinated minor bump across all published packages. - @hyperframes/cli 0.2.5 → 0.3.0 - @hyperframes/core 0.2.5 → 0.3.0 - @hyperframes/engine 0.2.5 → 0.3.0 - @hyperframes/player 0.2.7 → 0.3.0 - @hyperframes/producer 0.2.5 → 0.3.0 - @hyperframes/studio 0.2.9 → 0.3.0 Cuts a single versioned line under studio + player fixes that landed in #247 and #248 (root timeline DOM resolution, SSR-safe player load, and captions-internal import cleanup).
Merged
dahans-msft2
pushed a commit
to dahans-msft2/hyperframes
that referenced
this pull request
Aug 6, 2026
heygen-com#247) Bundled previews register a master composition alongside its sub-compositions in `window.__timelines`, e.g. { main, intro, scene2, scene5 }. Both the player's probe and studio's getAdapter() were using `keys[keys.length - 1]` to pick the adapter, which returned whichever timeline was registered last. That made the player report the final sub-composition's duration as the video length (e.g. 3.2s instead of the master's 14s) and play/pause/seek targeted that sub-composition instead of the full composition. Look up the outermost `[data-composition-id]` element in the iframe DOM and use its id to select the right timeline. Falls back to last-key when no element is present (standalone sub-composition previews) so drill-down views keep working. Also restores `main`/`import` entry points on @hyperframes/player to point at compiled dist output (the src/ paths broke workspace consumers that only receive the published tarball).
dahans-msft2
pushed a commit
to dahans-msft2/hyperframes
that referenced
this pull request
Aug 6, 2026
…m#248) * fix(studio): load @hyperframes/player lazily to support SSR Player.tsx had a bare `import "@hyperframes/player"` at module scope. The player package registers a class that extends HTMLElement as a side effect, and HTMLElement doesn't exist in a Node server runtime. Any consumer that imported from @hyperframes/studio during server-side rendering (e.g. the Next.js App Router evaluating a client component for SSR) threw `HTMLElement is not defined`. Move the import inside the mount effect via dynamic `import(...)` so it only runs in the browser, and wire up a cancellation flag and deferred cleanup so a fast unmount doesn't leak listeners or DOM nodes. * fix(studio): remove .js extensions from captions-internal imports The captions module imported sibling files as `./types.js` and `./parser.js`. That's legal ESM TypeScript, but Turbopack (and other bundlers) refuse to resolve those specifiers against .ts files when the package is consumed from node_modules — the rest of @hyperframes/studio uses extensionless imports for that reason. Align captions with the rest of the codebase so the package builds without bundler-specific configuration in consumers. * chore: release @hyperframes/[email protected] and @hyperframes/[email protected] Ships the root-timeline resolution fix (heygen-com#247), the SSR-safe player load, and the captions import cleanup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Bundled previews register the master composition alongside its sub-compositions in
window.__timelines:Both
@hyperframes/player's probe and@hyperframes/studio'suseTimelinePlayer.getAdapter()selected the adapter withkeys[keys.length - 1]. Object key ordering meant the last-registered sub-composition would win — so the player reported 3.2s as the video duration (fromscene5-logo-outro) instead of the master's 14s, andplay/pause/seekoperated on that sub-composition instead of the full composition.Fix
Resolve the root composition id from the DOM — the outermost
[data-composition-id]element is the master:This is authoritative — it uses the actual DOM structure rather than guessing by naming convention or registration order. Falls back to the last key when no
[data-composition-id]element exists (standalone sub-composition previews drilled-into via the studio) so that flow keeps working.Bonus
Also restores
main/importentry points on@hyperframes/player'spackage.jsonto point at the compileddist/output. Thesrc/paths introduced in #238 broke workspace consumers that only receive the published tarball (the tarball excludessrc/via"files": ["dist"]), producingModule not found: Can't resolve '@hyperframes/player'on build.Test plan
player.durationandPlayerControlstime display now report the master duration (14s) on a multi-composition bundled preview where the old code reported 3.2s