Build1 publisher3 min readPublished
Four parallel encodes and 11.4 Mbps leave the transcoder before anyone opens the player
A five-stage walkthrough of live video delivery publishes the ffmpeg command behind a four-rung ABR ladder. Its -hls_time 6 leaves every viewer at least a segment behind the camera, whatever the player does.
The Engineer · Build desk

What happened
- A dev.to walkthrough splits live delivery into five stages: ingest, transcode, package, CDN and client, with RTMP or SRT inbound, H.264/265 encoding, HLS or DASH packaging, HTTP edges and a player.
- Its production transcode command turns a single ingest feed into four video renditions: 6000k at 1080p, 3000k at 720p, 1500k at 480p and 800k at 360p.
- GOP size is pinned at 48 frames with scene-change detection disabled, holding keyframes in the same places across all four encodes; the article calls that critical for clean ABR switching.
- Packaging writes six-second segments and keeps ten per rendition in the live playlist, deleting older ones as the window moves.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- cost Ladder depth sets the transcode bill: four parallel x264 encodes and roughly 11.4 Mbps of continuous output per feed are paid for at zero viewers.
- constraint The player has no lever here: getting under six seconds means editing the encoder command and accepting three times the origin object count.
- decision The ingest protocol is chosen once at the encoder, and the choice weighs universal RTMP compatibility against SRT's forward error correction and RTT-tuned retransmission on unreliable links.
- exposure A client picking a rendition from the advertised 6000000 is working from a figure 728 kbps below what that rung is configured to emit at peak.
`-hls_time 6` tells the packager to collect six seconds of frames before the file exists [11]. Segment length is decided there, and the player inherits it. A client cannot request a file that has not been written, so the earliest a viewer sees a frame is six seconds after the encoder began that segment, before any network time [17]. HLS segments run 2 to 6 seconds in ordinary use [13]. Going from 6 to 2 triples the origin object count: 10 segments a minute per rendition becomes 30, and across four renditions 40 a minute becomes 120 [18].
Keyframe placement is what makes the four encodes interchangeable. The command sets `-g 48` and `-sc_threshold 0`, and the article calls a consistent GOP boundary critical for clean ABR switching [9][10]. The published line leaves output frame rate unset, so the rate arrives from the ingest [19]. At 24fps, 48 frames is two seconds and three GOPs fit a segment [9]. At 30fps the same flag gives 1.6 seconds, and a six-second segment is 3.75 of them [20]. What `-g 48` buys in seconds depends on the rate the camera actually sends.
Ladder depth is what the transcode bill tracks: one ingest becomes four parallel x264 encodes plus a single 128k AAC track at 44100 [23][8]. The video rungs sum to 11,300 kbps, so the packager pushes about 11.4 Mbps out continuously whether or not anyone is watching [16]. With `-hls_list_size 10` and `delete_segments`, ten files per rendition stay in the window, which is 60 seconds of video and 40 segment files alive at once [12][21].
The master playlist advertises `BANDWIDTH=6000000` for the 1080p rung [14]. That rung was configured with `-maxrate 6600k` over a 12000k bufsize and carries the shared audio [7][8], so a segment can peak at 6728 kbps, 728 above the number in the manifest [22].
The ingest protocol is a one-time choice at the encoder. RTMP is officially deprecated, runs over TCP port 1935, and remains the de facto choice because every encoder speaks it [4]. SRT, from Haivision, runs over UDP with AES-128/256 and forward error correction, and adjusts retransmission against measured round-trip time [5]. Encoder support has outweighed the deprecation notice.
The article presents these four rungs as "a typical production ABR ladder" [15]. For the ladder to transfer, your worst connection has to sustain roughly 800 kbps and your best device has to stop at 1080p [6]; the 360p rung is encoded baseline profile level 3.0, which is a bet about old decoders [24]. The piece opens on the gap between a stream loading in 200ms in Dublin and taking 4 seconds in rural Kerry [3], and its own point is that most developers aim a player at a URL and stop there [2]. The ffmpeg line is silent on that gap. Separating a slow manifest fetch from a slow first segment takes per-request timing at the client.
What to watch
- Whether encoder vendors move their shipped defaults from RTMP to SRT, since the deprecation on its own has not done it.
- Published edge timings for the Dublin and Kerry case, which would show whether the gap is distance or origin cache misses.
- Any revision that adds a 4K rung above the 1080p top, which changes the per-feed egress figure the current command produces.