# ShakaVideo

Video element powered by Shaka Player for DASH, HLS, and progressive playback with DRM

> **Caution: Unstable API**
>
> This API works today, but its shape is still settling and may change in a minor release. The implementation underneath is production quality; what is not final is how you configure it from Video.js. Pin your version and check the changelog when you upgrade.

Choose [Shaka Player](https://github.com/shaka-project/shaka-player) when one media component needs to play DASH, HLS, and progressive files, or when playback requires DRM.

## Import

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

```tsx
import { ShakaVideo } from '@videojs/react/media/shaka-video';
```

## Load a source

`src` takes a manifest URL. DASH, HLS, and progressive files all go through the same property, and Shaka picks the parser from the URL.

```tsx
<ShakaVideo src="https://example.com/manifest.mpd" />
```

When the URL carries no extension to go on, name the type with `source.type`. That’s what makes an extensionless manifest playable.

```tsx
<ShakaVideo source={{ src: 'https://example.com/manifest', type: 'application/dash+xml' }} />
```

## Protected content

`source.drm` names your license servers, keyed by [EME key system id](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess). Name every system you hold a license server for: which one gets negotiated is the browser’s choice.

```tsx
<ShakaVideo
  source={{
    src: 'https://example.com/manifest.mpd',
    drm: {
      'com.widevine.alpha': { licenseUrl: 'https://example.com/widevine' },
      'com.apple.fps': {
        licenseUrl: 'https://example.com/fairplay',
        serverCertificateUrl: 'https://example.com/fairplay.cer',
      },
    },
  }}
/>
```

FairPlay needs a `serverCertificateUrl` unless its CDM is pre-provisioned; Widevine and PlayReady ignore it. `source.drm` takes the same shape as hls.js’s own `drmSystems`, so one object describes DRM for either engine.

For the parts of Shaka’s DRM configuration this doesn’t cover, configure Shaka directly. A `drm.servers` under `source.engine.shaka` replaces `source.drm` rather than merging with it.

## Behavior

- Adaptation stays within renditions no larger than the element rendering them, through Shaka’s `abr.restrictToElementSize`. Override it under `source.engine.shaka`.
- `preload="none"` defers the load until playback is asked for; `autoplay` or a `play()` counts as asking.
- `preload="metadata"` loads, then holds Shaka’s buffering goals down to a second until `preload` rises to `auto`.
- `streamType` is detected from the manifest, so a player skin renders live and on-demand content correctly without being told which it is.
- Changing `source.engine.shaka` reconfigures the running player in place instead of recreating it.

## Examples

### Basic Usage

**App.tsx**

```tsx
import { ShakaVideo } from '@videojs/react/media/shaka-video';

export default function BasicUsage() {
  return <ShakaVideo className="shaka-video" src="https://dash.akamaized.net/akamai/streamroot/050714/Spring_4Ktest.mpd" autoPlay muted playsInline loop />;
}
```

**App.css**

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

## API Reference

### Props

Accepts the standard React props for a native `<video>`, plus these Video.js-specific props:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `preload` | `'' \| 'none' \| 'metadata' \| 'auto'` | `'metadata'` | How much to fetch before playback is asked for, mirroring the media element's own `preload`. Shaka has no split between "know the source" and "buffer it", so this maps onto when and how `engine.load()` runs:<br>- `'auto'` — load immediately with the configured buffering goals.<br>- `'metadata'` — load immediately, holding buffering to about a segment; the configured goals come back on the first play intent.<br>- `'none'` / `''` — hold the load entirely until the first play intent. A play intent is a `play` event, a target that is already playing, or `autoplay` — which the spec lets override `preload` for good reason: with nothing fetched there is nothing whose readiness could ever fire it. Widening (`none` → `auto`) takes effect immediately; narrowing after a load began cannot un-fetch and leaves it alone. |
| `source` | `{ src?: string; type?: string; drm?: Partial<Record<KeySystem, DrmSystemConfig>>; engine?: ShakaEngineConfig } \| null` | `null` | Structured source: what to play (`src`, an optional `type`) plus how to play it (`drm`, `engine.shaka`). Replacing it re-derives `src`. Shaka takes configuration on a live player, so changing `engine.shaka` re-applies it in place instead of recreating the engine. |
| `src` | `string` | `''` | |
| `streamType` | `'on-demand' \| 'live' \| 'unknown'` | `'unknown'` | |

### Ref

Forwards its ref to the rendered `<video>`. The ref is an [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement) and exposes its complete native property and method API.

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