# Assets and recordings

An **asset** is a video or audio file you can play on demand: a replay, a trailer, a lesson, a highlight. It is the on-demand side of Vabu Streams. Assets have ids that start `ast_`.

## Add an asset

There are two ways in.

**From a link.** Give a public HTTPS address of a video file.

```http
POST /v1/streams/assets
Idempotency-Key: replay-2026-10-11

{
  "url": "https://cdn.example.com/kasarani-night.mp4",
  "playback_policy": "signed",
  "generated_subtitles": "en",
  "external_id": "replay-kasarani-1011",
  "metadata": { "show": "Friday night" }
}
```

**From a browser upload.** Create an upload, then let your user's browser send the file straight to Vabu.

```http
POST /v1/streams/uploads
Idempotency-Key: upload-1011
```

The response holds a one-time `url`. `PUT` the file to it. Anyone who holds that address can upload, so treat it as a secret and set `cors_origin` to your site. When the file arrives the upload's `asset` is filled in and its `status` becomes `asset_created`.

## Status

A new asset has `status: "preparing"` while the video is processed. It becomes `ready` when it can be played, or `errored` with an `error` message when it cannot. You get an event for each: `streams.asset.ready` and `streams.asset.errored`. Do not offer an asset to viewers before it is `ready`. A playback request for an asset that is not ready is refused with `409 asset_not_ready`.

| Field | Meaning |
|---|---|
| `source` | Where the asset came from: `upload`, `url` or `clip`. `recording` will mark replays of live streams. Ignore values your code does not know. |
| `duration` | Length in seconds, once the asset is ready. |
| `audio_only` | `true` for sound with no picture. |
| `playback_ids` | How the asset is played. See [signed playback](https://docs.vabu.live/concepts/signed-playback.md). |
| `external_id`, `metadata` | Your own id and key and value pairs. Filter lists with `status`, `source`, `external_id` and `metadata[key]`. |

## Clips

A clip is a short piece cut from a ready asset. It becomes an asset of its own, with `source: "clip"`, and you play it like any other.

```http
POST /v1/streams/assets/ast_.../clips
Idempotency-Key: clip-1011-a

{ "start_time": 10, "end_time": 40.5 }
```

Times are seconds from the start of the asset. `end_time` must be after `start_time` and inside the asset. Fetch a clip with `GET /v1/streams/clips/{id}`.

## Play an asset

Give the customer an entitlement for the asset, with resource type `ast`, and open a session exactly as for a live stream. See [paid access](https://docs.vabu.live/guides/streams/paid-access.md) and [playback and sessions](https://docs.vabu.live/concepts/playback-and-sessions.md).

## Replays of live streams

Today you add a replay yourself: record the show at the venue, or save it from your encoder, and add the file as an asset. Replays recorded automatically from a live stream, with chapters, are on [What's coming](https://docs.vabu.live/whats-coming.md).
