# TwitchVideo

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/react/guides/skins) like any other media component; set `controls` to use Twitch’s UI instead.

## Import

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

```tsx
import { TwitchVideo } from '@videojs/react/media/twitch-video';
```

## 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.

```tsx
<TwitchVideo src="https://www.twitch.tv/videos/106400740" />
```

## 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`:

```tsx
<TwitchVideo
  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

**App.tsx**

```tsx
import { TwitchVideo } from '@videojs/react/media/twitch-video';

export default function BasicUsage() {
  return (
    <div className="twitch-video">
      <TwitchVideo src="https://www.twitch.tv/videos/106400740" controls />
    </div>
  );
}
```

**App.css**

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

## API Reference

### Props

Accepts these Video.js-specific props:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `autoplay` | `boolean` | `false` | |
| `controls` | `boolean` | `false` | |
| `defaultMuted` | `boolean` | `false` | |
| `loop` | `boolean` | `false` | |
| `muted` | `boolean` | `false` | |
| `playsInline` | `boolean` | `true` | |
| `poster` | `string` | `''` | |
| `preload` | `MediaPreloadType` | `'metadata'` | |
| `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` | `''` | |

### 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/react/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`. |

### Ref

Forwards its ref to the rendered `<iframe>`. The ref is an [HTMLIFrameElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement). Control playback with the component props and player APIs rather than the iframe ref.

### Events

Handle standard media events with React event props such as `onPlay` and `onTimeUpdate`. For native events without a React prop, attach a listener through the ref with `addEventListener`.

---

React documentation: https://videojs.org/docs/framework/react/llms.txt
All documentation: https://videojs.org/llms.txt
