> ## Documentation Index
> Fetch the complete documentation index at: https://docs.convertly.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Video Streaming

> HLS/DASH adaptive video streaming and transcoding.

Convertly Video Streams turn a stored video file into production-ready HLS or DASH/CMAF playback. The API creates a video asset, queues background encoding, generates manifests, bitrate renditions, captions, poster art, and returns playback URLs when the stream is ready.

Convertly can prepare streams with either the built-in packager or faster managed encoding for paid workspaces. Existing assets keep the provider they were created with.

Use Video Streams when your product needs browser/mobile playback instead of a single downloadable MP4: course videos, user-generated video, webinars, previews, clipping workflows, internal media libraries, and AI-generated highlight reels.

## Capabilities

| Capability         | Details                                                                                        |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| HLS VOD            | Generates a master playlist, rendition playlists, and segments.                                |
| DASH/CMAF          | Add `"dash"` to `packageFormats` to generate an MPEG-DASH manifest and CMAF segments.          |
| Adaptive bitrate   | Choose `basic`, `standard`, `hd`, `source_max`, or a custom ladder.                            |
| Codecs             | Choose `h264` for maximum compatibility or `av1` for lower bitrate delivery on modern clients. |
| Captions           | Attach WebVTT `subtitles` or `captions` tracks at asset creation.                              |
| Clipping           | Create streamable clips with `start`, `end`, `duration`, and `accurate` or `fast` mode.        |
| Signed playback    | Use expiring playback URLs, token TTLs, and optional allowed playback domains.                 |
| Playback analytics | The JS SDK can send play, pause, progress, seek, ended, and error events.                      |
| Poster frame       | Generates `poster.jpg` beside the stream.                                                      |
| Webhooks           | Emits `video.stream.started`, `video.stream.ready`, and `video.stream.failed`.                 |

## Create a stream

Upload a source video to Convertly Storage first, then create a stream from the stored file ID.

```bash theme={"system"}
curl -X POST "https://convertly.sh/api/video/streams" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceFileId": "5e8b2c74-19d3-4a6f-b082-c7e5419d36af",
    "profile": "hd",
    "packageFormats": ["hls", "dash"],
    "videoCodec": "h264",
    "access": "signed",
    "tokenTtlSeconds": 3600,
    "allowedDomains": ["app.example.com"],
    "segmentDuration": 6,
    "captions": [
      {
        "label": "English",
        "language": "en",
        "kind": "subtitles",
        "content": "WEBVTT\n\n00:00:00.000 --> 00:00:03.000\nWelcome."
      }
    ],
    "clip": {
      "start": 80,
      "end": 125,
      "mode": "accurate"
    }
  }'
```

The response is accepted immediately while the worker processes the stream:

```json theme={"system"}
{
  "stream": {
    "assetId": "vid_...",
    "playbackId": "pb_...",
    "status": "pending",
    "manifestUrl": null
  }
}
```

Poll `GET /api/video/streams/{id}` or subscribe to `video.stream.ready`.

## Profiles

| Profile      | Renditions                            |
| ------------ | ------------------------------------- |
| `basic`      | 360p, 720p                            |
| `standard`   | 360p, 480p, 720p                      |
| `hd`         | 360p, 480p, 720p, 1080p               |
| `source_max` | Up to 2160p when the source allows it |
| `custom`     | Your supplied rendition ladder        |

Convertly only generates renditions at or below the source height.

## Video codecs

`videoCodec` is optional and defaults to `h264`.

| Codec  | Use when                                                                                   | Notes                                                                                                                               |
| ------ | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `h264` | You need the safest browser, mobile, smart TV, and embed compatibility.                    | Uses H.264 High Profile with AAC audio. HLS uses MPEG-TS segments for SDR renditions and fMP4 for HDR10.                            |
| `av1`  | You want smaller streams for modern browsers and devices and can tolerate slower encoding. | Uses AV1 video with AAC audio in fMP4/CMAF segments. Test playback in your target players before making AV1 the only rendition set. |

AV1 is currently available on Convertly's built-in packager. Workspaces routed to managed Cloudflare Stream encoding still keep the AV1 option; selecting `av1` routes that asset through Convertly's video worker, while `h264` can use the configured managed provider. Existing assets keep the provider and codec selected when they were created.

Plan limits cap monthly processing and delivery. Source minutes count the input
duration once, regardless of the number of renditions generated. Delivery
minutes count viewer watch time. A 10 minute video watched fully by 100 viewers
uses 1,000 delivery minutes.

| Plan       | Video source minutes | Delivery minutes |
| ---------- | -------------------: | ---------------: |
| Free       |                   30 |            1,000 |
| Starter    |                  500 |            2,000 |
| Pro        |                1,500 |            7,000 |
| Business   |                7,500 |           40,000 |
| Enterprise |              250,000 |          500,000 |

All plans can generate the complete seven-rendition ladder through 2160p when
the source contains those pixels. Convertly does not upscale a lower-resolution
source into fake 4K. Pro and Business can use optional metered overage when it
is enabled in billing settings. See [Limits](/limits) for source and delivery minute allowances.

## Custom ladders

```json theme={"system"}
{
  "sourceFileId": "5e8b2c74-19d3-4a6f-b082-c7e5419d36af",
  "profile": "custom",
  "renditions": [
    { "height": 360, "bitrate": 700000, "audioBitrate": 96000 },
    { "height": 720, "bitrate": 2800000, "audioBitrate": 128000 },
    { "height": 1080, "bitrate": 5000000, "audioBitrate": 192000 }
  ]
}
```

## Playback

When `status` becomes `ready`, the stream includes:

```json theme={"system"}
{
  "manifestUrl": "https://cdn.convertly.sh/video/v1/pb_.../master.m3u8?expires=...&token=...",
  "hlsManifestUrl": "https://cdn.convertly.sh/video/v1/pb_.../master.m3u8?expires=...&token=...",
  "dashManifestUrl": "https://cdn.convertly.sh/video/v1/pb_.../manifest.mpd?expires=...&token=...",
  "posterUrl": "https://cdn.convertly.sh/video/v1/pb_.../poster.jpg?expires=...&token=..."
}
```

For built-in signed assets, Convertly validates the HMAC before every cache
lookup and rewrites playlist references so every rendition playlist and segment
carries the same expiring token. Public streams omit the token.

Some paid workspaces use managed encoding for faster transcoding. Those assets may return provider-hosted HLS/DASH URLs. Convertly mints signed playback tokens for you — you do not configure provider signing keys. When a signed URL expires, create a new playback session from the stream API.

Managed Cloudflare Stream mode requires `VIDEO_STREAM_PROVIDER=cloudflare_stream`, `CLOUDFLARE_STREAM_ACCOUNT_ID`, and `CLOUDFLARE_STREAM_API_TOKEN`. Signed playback additionally requires `CLOUDFLARE_STREAM_SIGNING_KEY_ID` and `CLOUDFLARE_STREAM_SIGNING_PRIVATE_KEY`. To show delivery minutes in Convertly Usage, run `POST /api/video/streams/cloudflare-usage-sync` on a schedule with `CLOUDFLARE_STREAM_SYNC_SECRET`. Set `CLOUDFLARE_STREAM_ANALYTICS_API_TOKEN` to a dedicated token scoped to the Stream account with **Account Analytics: Read**; ordinary Stream edit tokens cannot query the GraphQL Analytics API.

## JS player

Use **`@convertly-sh/player`** for a full HLS player with controls and analytics. See the [Video player](/docs/video-player) docs for install steps and an interactive embed.

For a minimal integration (your own UI + analytics only):

```ts theme={"system"}
import { bindPlaybackAnalytics } from "@convertly-sh/player";

bindPlaybackAnalytics({
  video: document.querySelector("video")!,
  playbackId: "pb_...",
});
```

The legacy `@convertly-sh/sdk` `ConvertlyPlayer` class still attaches captions and analytics to a raw `<video>` element, but does not include hls.js or custom controls — prefer `@convertly-sh/player` for new projects.

## Webhook payloads

`video.stream.ready` includes the asset ID, playback ID, duration, and generated renditions. `video.stream.failed` includes the error message.

```json theme={"system"}
{
  "type": "video.stream.ready",
  "data": {
    "assetId": "9a6d4f21-3c87-4e5b-b190-62f8d7a34ce5",
    "playbackId": "pb_...",
    "duration": 45,
    "renditions": [
      { "height": 360, "bitrate": 700000 },
      { "height": 720, "bitrate": 2800000 }
    ]
  }
}
```

## Operational notes

* HLS and DASH packaging runs asynchronously after you create a stream. Poll the stream status or listen for webhooks until the asset is `ready`.
* Source files must already exist in Convertly Storage.
* Built-in packaged manifests, posters, captions, and renditions count toward the same storage allowance as source files.
* Managed encoding copies the source to Convertly's video provider for faster packaging. Your library record stays in Convertly; delivery minutes still count toward your plan.
* Cloudflare Stream delivery minutes appear in Usage after the Cloudflare analytics sync job imports minutes viewed.
* AV1 requires the Convertly video worker's FFmpeg build to include `libsvtav1`.
* Deleting a built-in stream removes its packaged output. Deleting a managed-encoding asset also removes the remote packaged copy.
* Segment duration defaults to `6` seconds and may be set from `2` to `12`.
* Signed playback URLs expire after `tokenTtlSeconds`. Create a new signed playback session when the URL expires.
* Domain restrictions check the playback request `Origin` or `Referer` host when `allowedDomains` is set.
* DRM is tracked as planned in the asset response. It is not enforced yet.
