Skip to main content
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. 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. Live Inputs let you broadcast over RTMP/SRT and play back over HLS or WebRTC. Create a live input through the API or dashboard to receive ingest credentials, playback URLs, domain restrictions, and stream-key rotation — Convertly hosts the live infrastructure on Business and Enterprise plans.

Capabilities

CapabilityDetails
HLS VODGenerates a master playlist, rendition playlists, and segments.
DASH/CMAFAdd "dash" to packageFormats to generate an MPEG-DASH manifest and CMAF segments.
Adaptive bitrateChoose basic, standard, hd, source_max, or a custom ladder.
CaptionsAttach WebVTT subtitles or captions tracks at asset creation.
ClippingCreate streamable clips with start, end, duration, and accurate or fast mode.
Signed playbackUse expiring HMAC playback URLs, token TTLs, and optional allowed playback domains.
Playback analyticsThe JS SDK can send play, pause, progress, seek, ended, and error events.
Live inputsCreate RTMP/SRT ingest credentials, rotate keys, disable inputs, and return HLS/WebRTC playback URLs.
Poster frameGenerates poster.jpg beside the stream.
WebhooksEmits video.stream.started, video.stream.ready, and video.stream.failed.

Live broadcast

Create a live input to get a one-time stream key plus OBS-ready ingest settings.
curl -X POST "https://convertly.sh/api/live/inputs" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly product demo",
    "recordMode": "automatic",
    "reconnectWindowSeconds": 60,
    "allowedDomains": ["app.example.com"]
  }'
The response includes the stream key once:
{
  "streamKey": "cvlive_...",
  "liveInput": {
    "id": "00000000-0000-0000-0000-000000000000",
    "inputSlug": "live_...",
    "status": "idle",
    "ingest": {
      "obsServer": "rtmp://live.example.com:1935",
      "obsStreamKey": "live_...?token=cvlive_..."
    },
    "playback": {
      "hlsUrl": "https://live.example.com/live/v1/live_.../index.m3u8",
      "webRtcUrl": "https://live.example.com/live/webrtc/live_..."
    }
  }
}
Use POST /api/live/inputs/{id}/rotate-key to rotate a compromised key, PATCH /api/live/inputs/{id} to disable an input or update playback domains, and GET /api/live/inputs to monitor statuses. The dashboard’s Streams page has a Live inputs view with the same controls. Ingest and playback URLs are returned when you create or fetch a live input — use those values directly in your encoder and player. Domain restrictions and stream-key validation are enforced automatically before media is published or played back.

Manage live inputs

curl "https://convertly.sh/api/live/inputs" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY"
Rotate a stream key:
curl -X POST "https://convertly.sh/api/live/inputs/<input-id>/rotate-key" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY"
Disable an input:
curl -X PATCH "https://convertly.sh/api/live/inputs/<input-id>" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

Create a stream

Upload a source video to Convertly Storage first, then create a stream from the stored file ID.
curl -X POST "https://convertly.sh/api/video/streams" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceFileId": "00000000-0000-0000-0000-000000000000",
    "profile": "hd",
    "packageFormats": ["hls", "dash"],
    "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:
{
  "stream": {
    "assetId": "vid_...",
    "playbackId": "pb_...",
    "status": "pending",
    "manifestUrl": null
  }
}
Poll GET /api/video/streams/{id} or subscribe to video.stream.ready.

Profiles

ProfileRenditions
basic360p, 480p
standard360p, 480p, 720p
hd360p, 480p, 720p, 1080p
source_maxUp to 2160p when the source allows it
customYour supplied rendition ladder
Convertly only generates renditions at or below the source height. Plan limits also cap the final ladder:
PlanIncluded encoded minutesIncluded deliveryMax ladder
FreeNot includedNot includedNot included
StarterNot includedNot includedNot included
ProNot includedNot includedNot included
Business25,000 / month10 TB / month5 renditions, up to 2160p
Enterprise250,000 / month100 TB / month8 renditions, up to 2160p
Encoded minutes are calculated as stream duration multiplied by the number of renditions generated. Business can use optional metered overage when enabled in billing settings. Enterprise plans use contracted terms.

Custom ladders

{
  "sourceFileId": "00000000-0000-0000-0000-000000000000",
  "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:
{
  "manifestUrl": "https://convertly.sh/video/v1/pb_.../master.m3u8?expires=...&token=...",
  "hlsManifestUrl": "https://convertly.sh/video/v1/pb_.../master.m3u8?expires=...&token=...",
  "dashManifestUrl": "https://convertly.sh/video/v1/pb_.../manifest.mpd?expires=...&token=...",
  "posterUrl": "https://convertly.sh/video/v1/pb_.../poster.jpg?expires=...&token=..."
}
For signed assets, Convertly rewrites playlist references so every rendition playlist and segment carries the same expiring token. Public streams omit the query token and can be embedded directly.

JS player analytics

import { ConvertlyPlayer } from "@convertly/js";

new ConvertlyPlayer({
  video: document.querySelector("video")!,
  playbackId: "pb_...",
  manifestUrl: stream.hlsManifestUrl,
  posterUrl: stream.posterUrl,
  captions: stream.captions,
});
The player helper attaches WebVTT tracks and sends lightweight playback events to /api/video/playback-events. Use HLS.js or dash.js alongside it when the browser needs a manifest polyfill.

Webhook payloads

video.stream.ready includes the asset ID, playback ID, duration, and generated renditions. video.stream.failed includes the error message.
{
  "type": "video.stream.ready",
  "data": {
    "assetId": "00000000-0000-0000-0000-000000000000",
    "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.
  • Segment duration defaults to 6 seconds and may be set from 2 to 12.
  • Signed playback URLs expire after tokenTtlSeconds. Rotate a live input’s stream key or create a new signed playback session to cut off access sooner.
  • 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.