The player package provides a <hyperframes-player> custom element that embeds a HyperFrames composition anywhere — in any framework or plain HTML. Zero dependencies, 3KB gzipped.
When to Use
Use @hyperframes/player when you need to:
- Embed a rendered composition in a website, dashboard, or app
- Add a video-like player to a landing page or product demo
- Show compositions in documentation or blog posts
Use a different package if you want to:
- Edit compositions interactively — use the studio
- Preview during development — use the CLI (
npx hyperframes preview)
- Render to MP4 — use the CLI or producer
Quick Start
Via CDN
If you need a classic <script> tag instead of ESM, use the explicit global build:
Via npm
HTML Attributes
| Attribute | Type | Default | Description |
|---|
src | string | required | URL or relative path to composition HTML |
width | number | 1920 | Composition width in pixels |
height | number | 1080 | Composition height in pixels |
controls | boolean | false | Show playback controls overlay |
autoplay | boolean | false | Start playing on load |
loop | boolean | false | Loop playback |
muted | boolean | false | Mute audio (set to true for autoplay in most browsers) |
poster | string | — | Image URL to show before first play |
playback-rate | number | 1 | Playback speed multiplier |
JavaScript API
The player mirrors the native <video> element API:
Events
| Event | Detail | Description |
|---|
ready | { duration } | Composition loaded and timeline discovered |
timeupdate | { currentTime } | Fires during playback (~30fps) |
play | — | Playback started |
pause | — | Playback paused |
ended | — | Playback reached end |
error | { message } | Load or runtime error |
Framework Examples
React
Vue
Programmatic
Advanced: iframe access
The composition runs inside a sandboxed <iframe> in the player’s Shadow DOM. For most use cases you don’t need direct access — the JavaScript API and events above are sufficient. But if you’re building an editor, recorder, or custom timeline on top of the player, you’ll need to inspect the composition’s DOM or read its __player / __timelines runtime objects. The iframeElement getter exposes the inner iframe for these consumers:
This is the canonical way to bridge the player into editor tools like @hyperframes/studio. The studio exports a resolveIframe helper that handles both direct iframe refs and web-component refs:
React: declarative ref pattern
If you prefer JSX over imperative element creation, attach a ref to the web component and resolve the iframe inside an effect:
Common gotcha — if you pass the <hyperframes-player> element itself (not iframeElement) into a hook or API that expects an <iframe>, every .contentWindow / .contentDocument access returns null because the iframe lives inside the player’s Shadow DOM. Timeline seek, play, pause, and DOM inspection all silently no-op. Always extract iframeElement first, or use resolveIframe from @hyperframes/studio which handles both iframe and web-component hosts transparently.
Architecture
The player uses an iframe inside a Shadow DOM container. This provides:
- Isolation — composition CSS/JS can’t leak into or conflict with your page
- Security — iframe sandbox restricts composition capabilities
- Scaling — auto-scales the composition to fit the player’s container via CSS transforms
The player communicates with the composition via the HyperFrames runtime bridge protocol (postMessage). Existing compositions work without modification.
Controls
When the controls attribute is present, a minimal overlay appears at the bottom:
- Play/Pause button (left)
- Scrub bar with drag support (mouse + touch)
- Time display showing current / total duration (right)
- Auto-hides after 3 seconds of inactivity, reappears on hover