> ## Documentation Index
> Fetch the complete documentation index at: https://www.tella.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Embed API

> Control embedded Tella videos with JavaScript

# Embed API

The Tella Embed API allows you to control embedded videos using JavaScript's `postMessage` API. This enables you to build custom video experiences, synchronize playback with your application, and respond to playback events.

## Quick start

```html theme={null}
<iframe
  id="tella-player"
  src="https://www.tella.tv/video/YOUR_VIDEO_ID/embed"
  allow="autoplay; fullscreen"
></iframe>

<script>
  const iframe = document.getElementById("tella-player");

  // Wait for the player to be ready
  window.addEventListener("message", (event) => {
    if (event.data.type === "ready") {
      console.log("Player is ready!");
      // Now you can send commands
      iframe.contentWindow.postMessage(
        { type: "play" },
        "https://www.tella.tv",
      );
    }
  });
</script>
```

## Commands

Send commands to the embedded player using `postMessage`. All commands are sent as JSON objects with a `type` field.

<Note>
  Always wait for the `ready` event before sending commands to ensure the player
  is initialized.
</Note>

### Play

Start video playback.

```javascript theme={null}
iframe.contentWindow.postMessage({ type: "play" }, "https://www.tella.tv");
```

### Pause

Pause video playback.

```javascript theme={null}
iframe.contentWindow.postMessage({ type: "pause" }, "https://www.tella.tv");
```

### Seek

Jump to a specific time in the video.

| Parameter | Type   | Description                |
| --------- | ------ | -------------------------- |
| `time`    | number | Time in seconds to seek to |

```javascript theme={null}
// Seek to 30 seconds
iframe.contentWindow.postMessage(
  { type: "seek", time: 30 },
  "https://www.tella.tv",
);
```

### Mute

Mute the video audio.

```javascript theme={null}
iframe.contentWindow.postMessage({ type: "mute" }, "https://www.tella.tv");
```

### Unmute

Unmute the video audio.

```javascript theme={null}
iframe.contentWindow.postMessage({ type: "unmute" }, "https://www.tella.tv");
```

### Set volume

Set the video volume level.

| Parameter | Type   | Description                                    |
| --------- | ------ | ---------------------------------------------- |
| `volume`  | number | Volume level from 0 (muted) to 1 (full volume) |

```javascript theme={null}
// Set volume to 50%
iframe.contentWindow.postMessage(
  { type: "setVolume", volume: 0.5 },
  "https://www.tella.tv",
);
```

## Events

The embedded player sends events to the parent window. Listen for these events using `window.addEventListener`.

```javascript theme={null}
window.addEventListener("message", (event) => {
  // Verify the message is from Tella
  if (event.origin !== "https://www.tella.tv") return;

  const { type, ...data } = event.data;
  console.log("Event:", type, data);
});
```

### Ready

Sent once when the player is initialized and ready to receive commands.

```json theme={null}
{
  "type": "ready"
}
```

### Playback state

Sent when the playback state changes (play, pause, stop, etc.).

| Field         | Type   | Description                                                                    |
| ------------- | ------ | ------------------------------------------------------------------------------ |
| `state`       | string | Current state: `idle`, `playing`, `paused`, `stopped`, `seeking`, or `stalled` |
| `currentTime` | number | Current playback position in seconds                                           |
| `duration`    | number | Total video duration in seconds                                                |

```json theme={null}
{
  "type": "playbackState",
  "state": "playing",
  "currentTime": 15.5,
  "duration": 120.0
}
```

### Time update

Sent approximately every 250ms during playback to report the current time.

| Field         | Type   | Description                          |
| ------------- | ------ | ------------------------------------ |
| `currentTime` | number | Current playback position in seconds |
| `duration`    | number | Total video duration in seconds      |

```json theme={null}
{
  "type": "timeUpdate",
  "currentTime": 16.25,
  "duration": 120.0
}
```

## Complete example

Here's a complete example showing how to build a custom video controller:

```html theme={null}
<!DOCTYPE html>
<html>
  <head>
    <title>Custom Tella Player</title>
  </head>
  <body>
    <iframe
      id="player"
      src="https://www.tella.tv/video/YOUR_VIDEO_ID/embed"
      width="640"
      height="360"
      allow="autoplay; fullscreen"
    ></iframe>

    <div id="controls" style="display: none;">
      <button id="playBtn">Play</button>
      <button id="pauseBtn">Pause</button>
      <input type="range" id="progress" min="0" max="100" value="0" />
      <span id="time">0:00 / 0:00</span>
    </div>

    <script>
      const iframe = document.getElementById("player");
      const controls = document.getElementById("controls");
      const progress = document.getElementById("progress");
      const timeDisplay = document.getElementById("time");

      let duration = 0;
      const origin = "https://www.tella.tv";

      function formatTime(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins}:${secs.toString().padStart(2, "0")}`;
      }

      function send(message) {
        iframe.contentWindow.postMessage(message, origin);
      }

      // Listen for events from the player
      window.addEventListener("message", (event) => {
        if (event.origin !== origin) return;

        switch (event.data.type) {
          case "ready":
            controls.style.display = "block";
            break;

          case "playbackState":
          case "timeUpdate":
            duration = event.data.duration;
            const current = event.data.currentTime;
            progress.value = (current / duration) * 100;
            timeDisplay.textContent = `${formatTime(current)} / ${formatTime(
              duration,
            )}`;
            break;
        }
      });

      // Wire up controls
      document.getElementById("playBtn").onclick = () => send({ type: "play" });
      document.getElementById("pauseBtn").onclick = () =>
        send({ type: "pause" });

      progress.addEventListener("change", () => {
        const time = (progress.value / 100) * duration;
        send({ type: "seek", time });
      });
    </script>
  </body>
</html>
```

## Security considerations

<Warning>
  Always verify the `event.origin` when receiving messages to ensure they come
  from `https://www.tella.tv`.
</Warning>

When sending commands, you can use either the specific origin or `'*'`:

```javascript theme={null}
// Recommended: specify the exact origin
iframe.contentWindow.postMessage({ type: "play" }, "https://www.tella.tv");

// Also works but less secure
iframe.contentWindow.postMessage({ type: "play" }, "*");
```

## Embed URL parameters

You can customize the initial embed behavior using URL parameters:

| Parameter  | Values  | Description                       |
| ---------- | ------- | --------------------------------- |
| `autoPlay` | `true`  | Auto-play the video on load       |
| `loop`     | `1`     | Loop the video when it ends       |
| `muted`    | `1`     | Start the video muted             |
| `t`        | seconds | Start playback at a specific time |

```html theme={null}
<!-- Auto-play muted, starting at 30 seconds -->
<iframe
  src="https://www.tella.tv/video/ID/embed?autoPlay=true&muted=1&t=30"
></iframe>
```
