Guides
Adaptive streaming

Adaptive streaming

An adaptive bitrate job produces a ladder: the same video encoded several times at different resolutions and bitrates, plus a manifest that tells the player which rung to pull. The player switches rungs as the viewer's bandwidth changes, which is why streaming looks stable on a bad connection where a single 1080p file would stall.

What the presets give you

PresetRungsCodecPackagePlan
hls_abr_264_basic240p, 480p, 720pH.264 with AACHLS, CMAF fMP4Free
hls_abr_264_standard240p, 360p, 480p, 720p, 1080pH.264 with AACHLS, CMAF fMP4Pro
dash_abr_vp9_standardladderVP9 with OpusDASHPro
dash_abr_av1_efficient_1080pladder to 1080pAV1DASHBusiness
hls_abr_265_efficient_4kladder to 4KHEVCHLS, CMAF fMP4Enterprise
dash_abr_av1_efficient_4kladder to 4KAV1DASHEnterprise

The H.264 HLS ladders use six-second segments, a two-second GOP, and independent segments, so a player can switch rung at any segment boundary.

Here is the standard five-rung ladder in full:

RungResolutionPeak bitrateBufferAudio
1080p1920x10805200k10400k192k
720p1280x7202800k5600k128k
480p854x4801200k2400k96k
360p640x360600k1200k96k
240p426x240300k600k64k

The output is a ZIP

A streaming job produces many files, so the output is delivered as a single ZIP archive rather than a playable URL. Unpack it and you get:

master.m3u8         the multivariant playlist a player loads
manifest.json       an index of every file with its byte size
thumbnail.jpg       a frame taken from the source
v0/prog_index.m3u8  media playlist for the first rung
v0/seg_000.m4s      fMP4 segments for the first rung
v1/…                and so on, one directory per rung

DASH jobs have the same shape with an MPD manifest in place of the playlists.

manifest.json is there so you can enumerate and verify the archive without parsing playlists:

{
  "version": "1.0",
  "type": "hls-cmaf",
  "master": "master.m3u8",
  "files": [
    { "path": "master.m3u8", "bytes": 412 },
    { "path": "v0/prog_index.m3u8", "bytes": 1180 },
    { "path": "v0/seg_000.m4s", "bytes": 241664 }
  ]
}

Serving it

The signed link we give you points at the ZIP. That link is for you, not for your viewers: a player cannot stream from inside an archive, and the link expires. Unpack the archive and publish the files yourself.

curl -o hls.zip "$OUTPUT_URL"
unzip hls.zip -d ./hls
aws s3 sync ./hls s3://your-bucket/videos/9d1f5c0a/ --acl public-read

Point your player at master.m3u8 in the location you published to.

Two things break playback if you skip them:

Content types. Many object stores guess wrong. Serve .m3u8 as application/vnd.apple.mpegurl, .mpd as application/dash+xml, and .m4s as video/iso.segment. A playlist served as text/plain will not play.

CORS. If the player runs on a different origin from the files, the segment requests need permissive CORS headers, or the browser blocks them with no useful error.

Which one to pick

Start with hls_abr_264_basic. Three rungs cover most viewers, it is on every plan, and H.264 decodes everywhere.

Move to hls_abr_264_standard when you have 1080p sources worth delivering and an audience with the bandwidth for the top rung. The extra rungs cost encoding time, not playback quality.

Choose DASH over HLS when your player is browser-based and you want VP9 or AV1. Choose HLS when Apple devices matter, since Safari plays HLS natively.

Reach for the HEVC and AV1 ladders when bandwidth cost is the constraint and you control the client. They halve the bytes and narrow the set of devices that can play them.

Encoding time

A ladder encodes every rung, so it takes several times longer than one MP4 of the same source. The five-rung H.264 preset estimates 8 to 18 minutes for a typical source. Use a webhook rather than holding a request open.