If you have ever run video at any scale, you know the surprise. You upload a few hundred gigabytes, a clip does well, and suddenly the bandwidth line on your bill dwarfs everything else. The better your video performs, the more you pay. Your cost scales with your success, which is exactly backwards.
I got tired of that, so I built a video host where streaming is free and you only pay for storage. Here is how the architecture makes that possible.
Why video bills are mostly egress
Storage is cheap and predictable. A terabyte of video costs a few dollars a month to keep around. The expensive part is egress: the bytes sent to viewers every time someone presses play.
One hour of 1080p delivered to 1,000 viewers moves roughly 2.7 TB. At common CDN rates, that is real money, and it climbs linearly with every extra viewer. Mux meters minutes delivered. Cloudflare Stream charges per minute delivered. Bunny charges per GB delivered. Self hosting on S3 plus CloudFront is about $0.085 per GB of egress. Different units, same shape: a meter that ticks up with viewership.
The insight: meter the thing the customer controls
A customer controls how much they store. They do not control how popular their content gets. Billing on egress means billing on a number your customer cannot predict. That is what makes video bills unpredictable.
So the model I wanted was simple: meter storage, make delivery free. The only way to do that without going broke is to have no egress cost yourself.
The stack
Storage: Cloudflare R2.
R2 has no egress fees. That is the foundation. If your own delivery costs nothing, there is no bandwidth line to pass on to the customer.
Transcoding: FFmpeg plus Shaka Packager.
Every upload is transcoded into an adaptive HLS ladder with multiple renditions and short segments so playback adapts to each viewer's connection. This runs in a container triggered after upload completes.
Delivery: Workers at the edge, gated by signed tokens.
The HLS manifest and segments live in R2 and are served from Cloudflare's global edge. Before serving a byte, a Worker verifies a short lived HMAC playback token minted by the customer's backend. Video can be public, signed, or private, and leaked URLs expire quickly.
Player: an open source web component.
Instead of an iframe you cannot style or a React component that pulls in your entire stack, the player is a framework agnostic web component. One script tag, adaptive HLS via hls.js, a quality selector, and analytics beacons for play, heartbeat, and ended events. All requests are authenticated using the same playback token already in the source.
MIT licensed:
npm i reelm-player hls.js
<script type="module" src="https://cdn.jsdelivr.net/npm/reelm-player"></script>
<reelm-player src="https://your-host/master.m3u8?token={t}"></reelm-player>
Control plane: Hono API on Workers plus Postgres.
Handles auth, API keys, usage metering, and multi tenancy. Storage is the primary value metric. Processing minutes act as a secondary meter to prevent abuse.
The pricing that falls out
Because delivery costs nothing to run, the bill is just storage. Streaming and views are unlimited. A video can get 10 views or 10 million and the number does not change.
To be clear about the tradeoffs: at very low and steady viewership, a pure pay as you go host like Bunny can be cheaper in absolute terms. Where a storage billed model wins is predictability, and any workload where views are high relative to storage. The more your audience grows, the more a zero cost delivery model outperforms a per GB meter.
Try the pieces
- The player is open source and works with any HLS source, not just ours: https://github.com/deepan-alve/reelm-player, on npm as
reelm-player - A live demo with sample data, no signup: https://demo.reelm.video
- A calculator to compare costs on your own numbers: https://reelm.video/calculator
I am building this as Reelm. It is early, but the architecture is the interesting part, and the player is genuinely reusable on its own. Happy to answer questions about any of it.
Top comments (0)