ABR adaptive bitrate testing
Adaptive Bitrate streaming serves several renditions at once. Real viewers watch at different quality levels depending on connection speed, device and screen size. A load test that only fetches your highest-quality rendition misses the real traffic mix, and can miss bottlenecks that only appear under a mixed rendition load.
This page covers how ABR switching works, how to model a realistic viewer mix across renditions, and how to read the results in MaxoPerf.
Before you start
Section titled “Before you start”- Read HLS and DASH manifest and segment testing first. This page builds on the player simulation pattern from that page.
- Have your manifest URLs ready: master manifest, variant playlist URL for each rendition, and sample segment URLs for each rendition.
How ABR renditions affect load
Section titled “How ABR renditions affect load”A typical HLS or DASH stream offers 4–6 renditions, for example:
| Rendition | Bitrate | Segment size (4s) | Bytes/viewer/min |
|---|---|---|---|
| 240p | 400 Kbps | ~200 KB | ~3 MB |
| 480p | 1.2 Mbps | ~600 KB | ~9 MB |
| 720p | 2.5 Mbps | ~1.25 MB | ~18.75 MB |
| 1080p | 5 Mbps | ~2.5 MB | ~37.5 MB |
| 4K | 15 Mbps | ~7.5 MB | ~112.5 MB |
A viewer on a mobile network may use the 400 Kbps rendition. A desktop viewer on fiber climbs to 1080p. If your test only runs the 4K rendition, each VU pulls 20–40× more bytes than your average real viewer, and you run out of bandwidth before you reach the viewer concurrency you need to test. A 240p-only test has the opposite problem and puts too little stress on your origin.
Modeling a realistic viewer mix
Section titled “Modeling a realistic viewer mix”Split your test into several scenarios, one per rendition, weighted to match your real viewer distribution:
execution: # 60% of viewers on 720p (mobile + mid-tier desktop) - concurrency: 300 ramp-up: 2m hold-for: 10m scenario: viewer-720p
# 30% of viewers on 1080p (desktop, connected TV) - concurrency: 150 ramp-up: 2m hold-for: 10m scenario: viewer-1080p
# 10% of viewers on 480p (constrained mobile) - concurrency: 50 ramp-up: 2m hold-for: 10m scenario: viewer-480p
scenarios: viewer-720p: requests: - label: master-manifest url: https://cdn.example.com/stream/master.m3u8 method: GET - label: variant-playlist-720p url: https://cdn.example.com/stream/720p/playlist.m3u8 method: GET - label: segment url: https://cdn.example.com/stream/720p/seg-0001.ts method: GET - label: segment url: https://cdn.example.com/stream/720p/seg-0002.ts method: GET think-time: 4s - label: segment url: https://cdn.example.com/stream/720p/seg-0003.ts method: GET think-time: 4s - label: segment url: https://cdn.example.com/stream/720p/seg-0004.ts method: GET think-time: 4s
viewer-1080p: requests: - label: master-manifest url: https://cdn.example.com/stream/master.m3u8 method: GET - label: variant-playlist-1080p url: https://cdn.example.com/stream/1080p/playlist.m3u8 method: GET - label: segment url: https://cdn.example.com/stream/1080p/seg-0001.ts method: GET - label: segment url: https://cdn.example.com/stream/1080p/seg-0002.ts method: GET think-time: 4s # continue for segment coverage needed...
viewer-480p: requests: - label: master-manifest url: https://cdn.example.com/stream/master.m3u8 method: GET - label: variant-playlist-480p url: https://cdn.example.com/stream/480p/playlist.m3u8 method: GET - label: segment url: https://cdn.example.com/stream/480p/seg-0001.ts method: GET - label: segment url: https://cdn.example.com/stream/480p/seg-0002.ts method: GET think-time: 4sMaxoPerf runs all three execution blocks in parallel, which puts a realistic mixed-bitrate load on your CDN and origin at the same time.
Simulating bitrate switching within a session
Section titled “Simulating bitrate switching within a session”A viewer who starts on 720p and switches to 1080p mid-stream creates a different CDN request pattern. To model it, write a single viewer scenario that switches renditions partway through:
scenarios: viewer-with-quality-switch: requests: # Start on 720p - label: master-manifest url: https://cdn.example.com/stream/master.m3u8 - label: variant-playlist-720p url: https://cdn.example.com/stream/720p/playlist.m3u8 - label: segment-720p url: https://cdn.example.com/stream/720p/seg-0001.ts - label: segment-720p url: https://cdn.example.com/stream/720p/seg-0002.ts think-time: 4s - label: segment-720p url: https://cdn.example.com/stream/720p/seg-0003.ts think-time: 4s # Switch to 1080p — triggers a new playlist fetch + resync - label: variant-playlist-1080p url: https://cdn.example.com/stream/1080p/playlist.m3u8 - label: segment-1080p url: https://cdn.example.com/stream/1080p/seg-0004.ts think-time: 4s - label: segment-1080p url: https://cdn.example.com/stream/1080p/seg-0005.ts think-time: 4s - label: segment-1080p url: https://cdn.example.com/stream/1080p/seg-0006.ts think-time: 4sThe extra variant playlist fetch at the switch point is the detail that matters. CDN origin hit rates can shift a lot when many viewers upgrade their rendition at the same moment (for example, when a slow CDN region recovers and all players step up at once).
How to read ABR results in MaxoPerf
Section titled “How to read ABR results in MaxoPerf”In the results Overview tab, the per-label breakdown gives you latency for each rendition separately:
| What you see | What it means |
|---|---|
segment-720p p95 < 4000ms | CDN is serving 720p segments within the segment duration (good) |
segment-1080p p95 > 4000ms, segment-720p p95 OK | Origin is stressed for large segments; CDN miss-rate is high for 1080p |
variant-playlist-* latency rising | Manifest server under pressure, common when playlist generation is not cached |
Error rate spiking on segment-1080p only | 1080p rendition origin / storage tier is the bottleneck |
Do / don’t
Section titled “Do / don’t”Do:
- Base your rendition mix on real analytics data (average bitrate your users actually consume).
- Label requests with the rendition name so you can isolate which rendition is causing problems.
- Include a bitrate-switch scenario if your platform has frequent quality switches (e.g., mobile on variable networks).
Don’t:
- Test only your highest-quality rendition. It overstresses per-VU bandwidth and hides issues in lower-bitrate delivery paths.
- Assume all renditions perform equally. Packaging infrastructure, CDN rules and storage tiers often differ between renditions.
Where to go next
Section titled “Where to go next”- Concurrent viewers load: scale the viewer count and calculate the right VU-to-request-rate relationship.
- Live event streaming load: model the spike when viewers all switch from a lower bitrate to a higher one at live event start.
- Startup time and rebuffering QoE: derive QoE metrics from per-rendition latency.