> ## Documentation Index
> Fetch the complete documentation index at: https://hyperframes-chore-catalog-item-bundle.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# @hyperframes/player

> Embeddable web component for playing HyperFrames compositions in any web page.

The player package provides a `<hyperframes-player>` custom element that embeds a
HyperFrames composition in plain HTML or a framework application.

```bash theme={null}
npm install @hyperframes/player
```

Use Player when an application needs to play and seek an HTML composition. Use
[Studio](/packages/studio) to edit it or the [CLI](/packages/cli) and
[Producer](/packages/producer) to render a video file.

## Embed a composition

### Via CDN

```html title="index.html" theme={null}
<script type="module" src="https://cdn.jsdelivr.net/npm/@hyperframes/player"></script>

<hyperframes-player
  src="./my-composition/index.html"
  controls
  style="width: 100%; max-width: 800px; aspect-ratio: 16/9"
></hyperframes-player>
```

With a package manager:

```js theme={null}
import "@hyperframes/player";
```

```html title="index.html" theme={null}
<hyperframes-player
  src="/compositions/intro.html"
  controls
></hyperframes-player>
```

Set `autoplay muted` only when playback should start without a user gesture.

## Attributes

| Attribute               | Type               | Default  | Description                                                                |
| ----------------------- | ------------------ | -------- | -------------------------------------------------------------------------- |
| `src`                   | string             | —        | URL or relative path to composition HTML                                   |
| `srcdoc`                | string             | —        | Composition HTML already available as a string                             |
| `width`                 | number             | 1920     | Native composition width used for aspect ratio                             |
| `height`                | number             | 1080     | Native composition height used for aspect ratio                            |
| `controls`              | boolean            | false    | Show playback, scrub, speed, time, and volume controls                     |
| `autoplay`              | boolean            | false    | Start when the composition is ready                                        |
| `loop`                  | boolean            | false    | Restart at the end                                                         |
| `muted`                 | boolean            | false    | Mute audio                                                                 |
| `volume`                | number             | 1        | Playback volume from 0 to 1                                                |
| `poster`                | string             | —        | Image URL to show before first play                                        |
| `playback-rate`         | number             | 1        | Playback speed multiplier                                                  |
| `audio-src`             | string             | —        | Optional primary audio URL to preload in the parent frame                  |
| `audio-locked`          | boolean            | false    | Force muted playback and hide volume controls                              |
| `assets-loading-ui`     | `player` or `none` | `player` | `none` hides the loading-assets card; asset events still fire              |
| `low-power-idle`        | boolean            | false    | While paused, check in once a second, not every 80 ms (many-player pages)  |
| `disable-click-to-play` | boolean            | false    | A click on the player no longer plays or pauses, so the page can handle it |

Player also accepts `shader-capture-scale` and `shader-loading` for previewing
projects that use shader transitions. These are preview controls, not composition
authoring attributes.

## JavaScript API

The main API follows familiar media-player behavior:

```js theme={null}
const player = document.querySelector("hyperframes-player");

player.play();
player.pause();
player.seek(2.5);

player.currentTime = 5;
player.playbackRate = 1.5;
player.muted = true;

console.log(player.duration, player.paused, player.ready);
console.log(player.compositionWidth, player.compositionHeight);
```

## Events

```js theme={null}
const player = document.querySelector("hyperframes-player");

player.addEventListener("ready", (event) => {
  console.log("Duration:", event.detail.duration);
});

player.addEventListener("timeupdate", (event) => {
  console.log("Time:", event.detail.currentTime);
});
```

| Event            | Detail                                              | Description                                                  |
| ---------------- | --------------------------------------------------- | ------------------------------------------------------------ |
| `ready`          | `{ duration, compositionWidth, compositionHeight }` | Composition loaded and timeline discovered                   |
| `durationchange` | `{ duration }`                                      | The duration changed after `ready`                           |
| `resize`         | `{ compositionWidth, compositionHeight }`           | The composition's size changed                               |
| `timeupdate`     | `{ currentTime }`                                   | Playback position changed, approximately 10 times per second |
| `play`           | —                                                   | Playback started                                             |
| `pause`          | —                                                   | Playback paused                                              |
| `ended`          | —                                                   | Playback reached end                                         |
| `ratechange`     | —                                                   | Playback rate changed                                        |
| `volumechange`   | —                                                   | Volume or muted state changed                                |
| `scenes`         | `{ scenes }`                                        | The runtime reported its scene list                          |
| `error`          | `{ message }`                                       | Load or runtime error                                        |

## Advanced: iframe access

The composition runs inside an `<iframe>` in the player's Shadow DOM. For most
uses, the JavaScript API and events above are enough. The `iframeElement` getter
exists for same-origin tools that must inspect the composition DOM or connect a
custom editing surface:

```js theme={null}
const player = document.querySelector("hyperframes-player");
const iframe = player.iframeElement;

// Reach into the composition's DOM
iframe.contentDocument.querySelectorAll("[data-composition-id]");

// Read the runtime (GSAP timelines, element registry, etc.)
iframe.contentWindow.__timelines;
```

Direct DOM access works only when the composition and the host page are
same-origin. Cross-origin embeds must use the Player API and events.

[`@hyperframes/studio`](/packages/studio) exports `resolveIframe` for consumers
that need to pass the inner iframe to Studio's timeline hooks:

```ts theme={null}
import { resolveIframe, useTimelinePlayer } from "@hyperframes/studio";

const { iframeRef } = useTimelinePlayer();
const player = document.createElement("hyperframes-player");
player.setAttribute("src", src);
container.appendChild(player);

// Forward the inner iframe so useTimelinePlayer can drive play/pause/seek.
iframeRef.current = resolveIframe(player);
```

## How it works

The composition runs in a sandboxed iframe inside the player's Shadow DOM. This
isolates its styles, scales it to the player container, and lets the player
communicate with the HyperFrames runtime through `postMessage`.

## Related topics

* [Edit the same composition with the SDK](/sdk/quickstart)
* [Use the complete Studio interface](/studio)
* [Understand the composition contract](/reference/html-schema)
