# twitch-video

Video component that plays Twitch videos and live channels through the Twitch embed player

The [Twitch embed player](https://dev.twitch.tv/docs/embed/video-and-clips/) handles both recorded videos and live channels. Its own chrome stays hidden by default, so it drops into a [player skin](https://videojs.org/docs/framework/html/guides/skins) like any other media component; set `controls` to use Twitch’s UI instead.

## Import

```bash
pnpm add @videojs/twitch-video
```

```ts
import '@videojs/html/media/twitch-video';
```

Or load it from the [CDN](https://videojs.org/docs/framework/html/guides/cdn):

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0-rc.4/media/twitch-video.js"></script>
```

## Load a source

`src` takes a video URL (`twitch.tv/videos/<id>`) or a channel URL (`twitch.tv/<channel>`), with or without the `www.` and `go.` hosts. A channel URL plays the channel’s live stream. Clips (`clips.twitch.tv`) are a different embed and aren’t supported.

```html
<twitch-video src="https://www.twitch.tv/videos/106400740"></twitch-video>
```

## Live channels

A channel embed behaves like a live media component:

- `duration` reports `Infinity` while the stream is live.
- Seeking is unavailable: the embed exposes no DVR window.
- The stream going away and coming back dispatch `offline` and `online` events.
- `loop` never repeats a channel; a live stream doesn’t end.

## Parent hostnames

Twitch checks the embedding page’s ancestors against a `parent` allowlist and won’t play unless the current page is on it. The element always includes your page’s own hostname, so a plain embed needs no setup. When your player is itself framed by other hostnames, name each of them under `engine.twitch.parent`:

```ts
const video = document.querySelector('twitch-video');
video.source = {
  src: 'https://www.twitch.tv/videos/106400740',
  engine: { twitch: { parent: ['embed.example.com'] } },
};
```

## Behavior

- Volume and mute both work, like a native `<video>`.
- `playbackRate` is reported but never applied: the embed has no rate command.
- `loop` restarts a finished video from the top; the embed has no loop parameter.
- `controls` is read when the embed is built; changing it later doesn’t take effect, since rebuilding the iframe would lose the playback session.
- Fullscreen targets the iframe, so Twitch’s own chrome shows in fullscreen.

## Examples

### Basic Usage

**index.html**

```html
<twitch-video class="twitch-video" src="https://www.twitch.tv/videos/106400740" controls></twitch-video>
```

**index.css**

```css
.twitch-video {
  width: 100%;
  aspect-ratio: 16 / 9;
}
```

**index.ts**

```ts
import '@videojs/html/media/twitch-video';
```

## API Reference

### Attributes

These attributes configure the embedded media adapter:

| Attribute | Type | Default |
| --- | --- | --- |
| `autoplay` | `boolean` | `false` |
| `controls` | `boolean` | `false` |
| `loop` | `boolean` | `false` |
| `muted` | `boolean` | `false` |
| `playsinline` | `boolean` | `true` |
| `poster` | `string` | `''` |
| `preload` | `MediaPreloadType` | `'metadata'` |
| `src` | `string` | `''` |

### Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `autoplay` | `boolean` | `false` | |
| `buffered` | `TimeRangeLike` | — | Read-only. |
| `controls` | `boolean` | `false` | |
| `currentSrc` | `string` | — | Read-only. |
| `currentTime` | `number` | — | |
| `defaultMuted` | `boolean` | `false` | |
| `duration` | `number` | — | Read-only. |
| `ended` | `boolean` | — | Read-only. |
| `engine` | `Window \| null` | — | Read-only. The embed's own window, which every command is posted to. Null until an embed is bound and in a document. |
| `error` | `MediaError \| null` | — | Read-only. |
| `isFullscreen` | `boolean` | — | Read-only. |
| `loop` | `boolean` | `false` | |
| `muted` | `boolean` | `false` | |
| `paused` | `boolean` | — | Read-only. |
| `playbackRate` | `number` | — | |
| `played` | `{ length: number; start(index: number): number; end(index: number): number }` | — | Read-only. |
| `playsInline` | `boolean` | `true` | |
| `poster` | `string` | `''` | |
| `preload` | `MediaPreloadType` | `'metadata'` | |
| `readyState` | `number` | — | Read-only. |
| `seekable` | `TimeRangeLike` | — | Read-only. |
| `seeking` | `boolean` | — | Read-only. |
| `source` | `{ src?: string; engine?: TwitchSourceEngineConfig } \| null` | `null` | Twitch VOD or channel URL in `src`, plus embed parameters under `engine.twitch`. Replacing it re-derives `src`. |
| `src` | `string` | `''` | |
| `textTracks` | `TextTrackListLike` | — | Read-only. |
| `volume` | `number` | — | |

### Engine options

#### `source.engine.twitch`

Pass [Twitch embed parameters](https://dev.twitch.tv/docs/embed/video-and-clips/) under `source.engine.twitch`, spelled exactly as Twitch spells them, plus anything Twitch adds next. [Media Sources](https://videojs.org/docs/framework/html/guides/media-sources) covers how engine options fit into a structured source.

`controls`, `autoplay`, and `muted` come from the props of the same name, and the video or channel comes from `src`, so none of those have an `engine.twitch` spelling.

| Option | Type | Description |
| --- | --- | --- |
| `collection` | `string \| undefined` | Collection to play through, starting from the video named by `src`. |
| `parent` | `string \| readonly string[] \| undefined` | Every hostname the embed may be framed by. Twitch checks the frame's ancestors against it and refuses to play when the current page is missing, which is why the page's own hostname is always included on top of this. |
| `referrerPolicy` | `ReferrerPolicy \| undefined` | `referrerpolicy` for the embed iframe. Not a Twitch embed parameter, so it never reaches the URL: the React player applies it to the iframe it renders, and the HTML player reads its own `referrerpolicy` attribute instead. |
| `time` | `string \| undefined` | Start position, spelled the way Twitch spells timestamps: `1h30m10s`. |

### Methods

Supports these media methods: `exitFullscreen`, `load`, `pause`, `play`, `requestFullscreen`.

### Events

Implements these standard media events through the embedded player: `durationchange`, `emptied`, `ended`, `error`, `loadedmetadata`, `loadstart`, `playing`, `progress`, `seeked`, `seeking`, `timeupdate`, `volumechange`, `waiting`.

Also emits these Video.js-specific events:

| Event | Description |
| --- | --- |
| `loadcomplete` | |
| `sourcechange` | Fired when `source` changes, either directly or by resolving a new `src`. Read `source` for the new value. |

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
