# DRM: content protection for VOD and live

> How to turn on DRM for a recorded asset or a live input, what the player and the license server do, and how to connect a DRM vendor for Widevine, PlayReady and FairPlay.

FirstByte Stream can encrypt your media with **Common Encryption (CENC),
scheme `cbcs`**. One encrypted copy serves every playback path (MoQ, HLS and
DASH) and every key system (Clear Key, Widevine, PlayReady and FairPlay). The
relays only carry encrypted media. They never have the keys.

## Key systems

| Key system | Needs a DRM vendor | Protection |
| --- | --- | --- |
| **Clear Key** (W3C) | No | Encrypts the media. The key gets to the page's JavaScript, so Clear Key does not prevent copying. |
| **Widevine** (Chrome, Firefox, Android) | Yes | The key stays in the browser's CDM. |
| **PlayReady** (Edge, Windows, smart TVs) | Yes | The key stays in the CDM. |
| **FairPlay** (Safari, iOS) | Yes | The key stays in the CDM. |

Without a DRM vendor, protected media uses Clear Key. When you connect a vendor
(see [DRM provider](#drm-provider)), the player uses the best key system that
the viewer's browser supports.

## Turn on DRM for a recorded asset

Before you turn on DRM, make sure that:

- your organization has an active **Ed25519 playback signing key**,
- **Auto-transcode (ABR)** is on in the VOD defaults.

Then open the asset's **playback endpoints** and turn on **DRM**, or use the API:

```ts
await client.streams.assets.setDrm.mutate({ orgId, id: assetId, enabled: true });
```

The asset is encoded again. It is not available until the new encode is ready.
After that:

- The player gets its keys from `/api/streams/playback/<pb>/license` (or from
  the license proxy for a vendor key system), with a playback token.
- `/source`, the MP4 download and `assets.playbackUrl` refuse a DRM asset,
  because they would give the clear original.

## Turn on DRM for a live input

Live DRM works for inputs that you publish over **RTMP** or **SRT**. The
ingest encrypts the media before the stream gets to a relay.

Open the live input and turn on **DRM** in the **DRM** card, or use the API:

```ts
await client.streams.liveInputs.setDrm.mutate({ orgId, id: liveInputId, enabled: true });
```

- The change applies at the next publish. If the input is live now, stop the
  encoder and start it again.
- The input then refuses publishing over WHIP and MoQ, because those paths
  cannot be encrypted by the platform. Use RTMP or SRT.
- If the platform cannot load the input's keys, it refuses the encoder (ingest
  error `drm_keys_unavailable`). It never publishes a DRM input in the clear.
- When you turn DRM off, the keys stay stored. If you turn DRM on again, the
  same keys are used.

## What the viewer needs

The `<clutchcall-player>` element and `StreamPlayer` do DRM by
themselves. The browser must support Encrypted Media Extensions (EME).

- For a protected asset, the player never falls back to a clear path. If the
  browser cannot decrypt, the player shows an error.
- Safari without a FairPlay vendor cannot play Clear Key through native HLS.

## DRM provider

A DRM vendor gives Widevine, PlayReady and FairPlay licenses. Connect one in
**Settings → Content protection**, or with `streams.drm.setProvider`. Only an
owner or an admin can change it.

| Field | Meaning |
| --- | --- |
| Kind | `cpix`, or a vendor preset: `axinom`, `ezdrm`, `pallycon`, `buydrm`, `irdeto`. `none` turns the provider off. |
| CPIX URL | The vendor's CPIX 2.3 key endpoint. The platform gets content keys and the pssh data for each system from it. |
| Systems | The key systems to use: `widevine`, `playready`, `fairplay`. |
| License URLs | The vendor's license server URL for each system, and the FairPlay certificate URL. |
| Credentials | Header values for the CPIX and license calls. They are stored sealed and are never shown again. |

All URLs must start with `https://` and must not point at a private address.

Use **Test provider** (`streams.drm.testProvider`) to check the CPIX connection
before you save.

### How licensing works with a vendor

The player sends its license request to the platform's **license proxy**, not
to the vendor:

```
POST /api/streams/playback/<id>/license/widevine
POST /api/streams/playback/<id>/license/playready
POST /api/streams/playback/<id>/license/fairplay
GET  /api/streams/playback/<id>/license/fairplay/certificate
```

The proxy checks the viewer's playback token, adds your sealed vendor
credentials, and sends the request to the vendor. Your vendor credentials never
get to the browser.

### Limits

- Keys that were made before you connected a provider stay Clear Key keys.
  Turn DRM off and on again for an asset to get vendor keys.
- The CPIX client accepts keys in plain text over TLS. It refuses keys that are
  encrypted with a document key.
- Vendors that need a new token for each license request are not supported.
  Only fixed credential headers are supported.
- Live inputs carry only the common pssh box in the init segment.
