Repro
Server-side compose a minimal HTML5 composition file matching the canonical blank template, served from a public URL with Access-Control-Allow-Origin: *. Composition source:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1280, height=720" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { margin: 0; width: 1280px; height: 720px; overflow: hidden; background: #0f172a; }
#root { width: 100%; height: 100%; position: relative; display: flex; align-items: center; justify-content: center; }
#title { font-family: -apple-system, sans-serif; font-size: 128px; font-weight: 700; color: #fff; }
</style>
</head>
<body>
<div id=\"root\" data-composition-id=\"main\" data-start=\"0\" data-duration=\"5\" data-width=\"1280\" data-height=\"720\">
<div id=\"title\" class=\"clip\" data-start=\"0\" data-duration=\"5\" data-track-index=\"0\">It works</div>
</div>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
tl.from('#title', { opacity: 0, y: 30, duration: 0.8, ease: 'power2.out' }, 0)
.to('#title', { opacity: 0, y: -20, duration: 0.6, ease: 'power2.in' }, 4.4);
window.__timelines['main'] = tl;
</script>
</body>
</html>
Embed in a parent page (same-origin) via:
<script type=\"module\" src=\"https://unpkg.com/@hyperframes/player@0.5.3\"></script>
<hyperframes-player src=\"/compositions/2\" shader-loading=\"none\" controls></hyperframes-player>
Expected
Clicking play (or setting player.currentTime = 2) should advance the registered GSAP timeline so that window.__timelines['main'].time() follows playback and the visible state of #title animates.
Actual
The player loads, parses metadata correctly:
- duration is reported as 5 (visible in the controls UI as
0:00 / 0:05)
customElements.get('hyperframes-player') is defined
- iframe is same-origin (verified — the parent can read
iframe.contentDocument, __timelines.main, gsap, #title)
But:
- Calling
player.play() flips paused=false but currentTime doesn't advance.
- Setting
player.currentTime = 2 updates the player's reported value, but window.__timelines['main'].time() stays at 0.
- The composition iframe's window has none of the Hyperframes runtime markers (no
__hf* keys, no postMessage handlers I could detect).
- Manually calling
tl.time(2) from the parent works correctly — at t=2 the #title element transitions to opacity 1, transform identity. So the timeline itself is healthy.
It looks like the player isn't injecting (or isn't running) its seek runtime in the iframe in src=URL mode, so even though the parent ↔ iframe relationship is same-origin, the seek bridge never fires.
Environment
- @hyperframes/player 0.5.3 from unpkg
- Chrome (latest)
- Composition served from same origin as the embedding page (CORS open just in case)
- No CSP on either side
- iframe is sandboxed by the player; same-origin access still works for inspection
Notes / hypothesis
Looking at the player's prototype methods I see both _prepareSrc and _prepareSrcdoc plus _injectRuntime and _promoteToParentProxy. My guess is _injectRuntime runs only on the srcdoc path or after a specific iframe load signal that isn't firing for src-mode same-origin loads. Happy to test a patch or grab more diagnostic output if useful.
Repro
Server-side compose a minimal HTML5 composition file matching the canonical blank template, served from a public URL with
Access-Control-Allow-Origin: *. Composition source:Embed in a parent page (same-origin) via:
Expected
Clicking play (or setting
player.currentTime = 2) should advance the registered GSAP timeline so thatwindow.__timelines['main'].time()follows playback and the visible state of#titleanimates.Actual
The player loads, parses metadata correctly:
0:00 / 0:05)customElements.get('hyperframes-player')is definediframe.contentDocument,__timelines.main,gsap,#title)But:
player.play()flipspaused=falsebutcurrentTimedoesn't advance.player.currentTime = 2updates the player's reported value, butwindow.__timelines['main'].time()stays at 0.__hf*keys, nopostMessagehandlers I could detect).tl.time(2)from the parent works correctly — at t=2 the#titleelement transitions to opacity 1, transform identity. So the timeline itself is healthy.It looks like the player isn't injecting (or isn't running) its seek runtime in the iframe in
src=URLmode, so even though the parent ↔ iframe relationship is same-origin, the seek bridge never fires.Environment
Notes / hypothesis
Looking at the player's prototype methods I see both
_prepareSrcand_prepareSrcdocplus_injectRuntimeand_promoteToParentProxy. My guess is_injectRuntimeruns only on the srcdoc path or after a specific iframe load signal that isn't firing for src-mode same-origin loads. Happy to test a patch or grab more diagnostic output if useful.