# Segment Desk > A live stream's segment duration decides three things at once, and only two of them > are its own. The live edge sits (buffer + 1) x segment back and a viewer makes > 60 / segment requests a minute: both belong to the segment. The bitrate belongs to the > KEYFRAME interval, because a group of pictures runs from one IDR to the next. They get > conflated because the ordinary setup makes them equal - which is why an ordinary 6 s stream > sits 24 s behind, and why cutting it to 2 s reaches 8 s for no bitrate at all. ## The one thing to know **ONE NUMBER DECIDES THREE THINGS, AND ONLY TWO OF THEM ARE ITS OWN.** ```text live edge = (segments the player buffers + 1) x segment duration requests = 60 / segment duration, per rung, per viewer group cost = (I-frame cost + (frames in the group - 1)) / frames in the group frames = keyframe interval x frame rate cuts cleanly = round(segment x fps) mod round(keyframe x fps) == 0 ``` The first two never mention the keyframe interval. The third never mentions the segment. They meet only in the last line, and it is a DIVISIBILITY constraint rather than a proportionality - which is why a shorter segment is sometimes free and sometimes ruinous, with nothing in between. Worked: a 6 s segment cut at 2 s keyframes, 30 fps, a 3-segment player buffer. The live edge is 24 s against a 10 s budget. Cut the segment to 2 s and the live edge is 8 s - **and the bitrate does not move**, +9.5% to +9.5%, because the 2 s keyframes still divide the shorter segment. Cut it to 2.5 s instead - the longest segment meeting the budget exactly - and it costs +29.5%, because 2.5 s is 75 frames at 30 fps and the longest whole-frame interval dividing 75 is 25. ## What every length costs | Segment | Live edge | Group of pictures | Bitrate vs 6 s | Requests | Reads as | | --- | --- | --- | --- | --- | --- | | **1 s** | 4 s | 30 frames | +23.8% | 60 a minute | interactive | | **2 s** | 8 s | 60 frames | +9.5% | 30 a minute | ordinary | | **4 s** | 16 s | 120 frames | +2.4% | 15 a minute | broadcast-like | | **6 s** | 24 s | 180 frames | 0% | 10 a minute | broadcast-like | | **10 s** | 40 s | 300 frames | -1.9% | 6 a minute | broadcast-like | At 30 fps, with a player buffering 3 segments and an I-frame costing 10× a P-frame. Between the top row and the bottom the live edge moves 10× — from 4 s to 40 s — and the bitrate moves the other way by 25.7 points. **Every column that improves going down the table is paid for by a column that gets worse.** There is no row that wins. ## The same interval at other frame rates | Frame rate | 1 s segment | 2 s segment | 4 s segment | | --- | --- | --- | --- | | **24 fps** | +29.4% (24 frames) | +11.8% (48 frames) | +2.9% (96 frames) | | **25 fps** | +28.3% (25 frames) | +11.3% (50 frames) | +2.8% (100 frames) | | **30 fps** | +23.8% (30 frames) | +9.5% (60 frames) | +2.4% (120 frames) | | **50 fps** | +14.6% (50 frames) | +5.8% (100 frames) | +1.5% (200 frames) | | **60 fps** | +12.2% (60 frames) | +4.9% (120 frames) | +1.2% (240 frames) | A one-second segment costs +29.4% at 24 fps and +12.2% at 60 fps — the same duration, 2.4× the penalty. **A high frame rate can afford a shorter segment than a low one.** People assume the heavier format is the constrained one; for this setting it is the other way round. ## What divides what | Segment | Keyframe | Rate | Segment frames | Keyframe frames | Keyframes per segment | Cuts on its own boundary | | --- | --- | --- | --- | --- | --- | --- | | 6 s | 2 s | 30 fps | 180 frames | 60 frames | 3 | yes | | 6 s | 2.5 s | 60 fps | 360 frames | 150 frames | 2.4 | **NO** | | 4 s | 2 s | 30 fps | 120 frames | 60 frames | 2 | yes | | 4 s | 4 s | 25 fps | 100 frames | 100 frames | 1 | yes | | 2 s | 2 s | 29.97 fps | 60 frames | 60 frames | 1 | yes | | 6 s | 4 s | 30 fps | 180 frames | 120 frames | 1.5 | **NO** | The check is in FRAMES, not seconds, because the encoder counts frames. `6 s / 2.5 s` looks like it might be close enough; at 60 fps it is 360 frames against 150, which is 2.4 groups to the segment, and the third segment boundary of every pair lands inside a group. The row at 29.97 fps passes because both sides round the same way — this check rounds each side to whole frames before dividing, which is what the encoder does. ## Thresholds | Threshold | Value | What it separates | | --- | --- | --- | | interactive | live edge ≤ 5 s | a viewer can react to what they are watching. Needs segments of 1.3 s or shorter at a 3-segment buffer. | | ordinary | live edge ≤ 15 s | where most streamed events sit — up to 3.8 s segments. | | broadcast-like | above that | social media is ahead of the picture. | | notable overhead | ≥ 5% against 6 s | measurable; most people spend it for the latency. | | gross overhead | ≥ 20% | a large share of the bill, bought entirely for latency. | | busy | ≥ 30 a minute per viewer per rung | a request every 2 s or faster. | Defaults when the sheet is silent: 30 fps, a 3-segment player buffer, an I-frame at 10× a P-frame, and 6 s as the bitrate reference. Every one of those is stated as a finding when it is assumed, because all four change the answer. ## Sheet grammar Two blocks. `STREAM` is `key | value`, one per line. `RENDITIONS` is a table. ``` STREAM name | what this stream is fps | 30 frames a second segment | 6s the one number this page is about keyframe | 2s IDR spacing; must divide the segment in whole frames buffer | 3 whole segments the player holds before it starts iframe | 10 what an I-frame costs relative to a P-frame target | 10s the live-edge budget every verdict is measured against reference| 6s the segment length overheads are quoted against RENDITIONS r1 | 1080p | 5 Mbps | 30 | the top rung r2 | 720p | 2800 | | fps blank means the stream's rate ``` A RENDITIONS row is `id | what it is | bitrate | fps | why`. Bitrate accepts `5 Mbps`, `5000k` or a bare number in kilobits. A duration accepts `6`, `6s` or `2000ms` — a bare number is SECONDS. Only `segment` is really required; everything else has a default, and every default that gets used is reported as a finding. `keyframe` defaults to the segment duration, which is the ordinary setup and the one case where the segment and the group of pictures are the same thing. ## Lanes - **`plan`** — Choose the segment before anything is encoded. Segment duration gets chosen once, usually by copying whatever the last stream used, and it then decides the latency, the bitrate and the request rate for the life of the product. This takes what the stream is for and picks the length deliberately, with all three consequences priced. Sections: Summary, The Sheet, The Setting, Reasoning, Next Step. - **`check`** (primary) — What this configuration actually costs. The paid read of what the free panel computes. Where the live edge sits and why, what the keyframe spacing costs in bitrate, how many requests a viewer makes, and whether every rung of the ladder can be cut on its own boundary. Sections: Summary, Verdict, Findings, Corrected Sheet, Next Step. - **`trade`** — The three consequences, side by side. One table at every segment length people actually ship, with the live-edge latency, the bitrate against a reference, the group of pictures and the request rate in the same row — so the trade can be read rather than argued about. Sections: Summary, At Every Length, What Moves Together, Where To Sit, Next Step. - **`ladder`** — Whether the ladder can switch. A player changing rung has to find a boundary that exists in both, so every rendition must be cut at the same instants. This checks the keyframe interval against the segment in FRAMES at every rung's own rate, which is where the rounding happens and where mixed frame rates come apart. Sections: Summary, Every Rung, What Divides What, What A Switch Costs, Next Step. - **`deliver`** — Decide what changes: the segment, the ladder, or the expectation. Sorts every finding into what a different segment length fixes, what only the ladder fixes, and what nothing fixes because it is what segmenting costs. The last bucket is bigger than people expect: latency below a segment is not available at any price without changing the protocol. Sections: Summary, A Shorter Segment Fixes, Only The Ladder Fixes, Nothing Fixes, Next Step. ## Findings All 32 are computed in the browser and cost nothing. | Code | Severity | Scope | What it means | | --- | --- | --- | --- | | `FPS-ASSUMED` | warn | stream | The frame rate was assumed | | `SEGMENT-ASSUMED` | warn | stream | The segment duration was assumed | | `KEYFRAME-ASSUMED` | note | stream | The keyframe interval was assumed | | `BUFFER-ASSUMED` | note | stream | The player's buffer depth was assumed | | `IRATIO-ASSUMED` | note | stream | The cost of an I-frame was assumed | | `TARGET-ASSUMED` | warn | stream | The latency budget was assumed | | `NO-RENDITIONS` | warn | stream | No renditions given | | `ONE-RENDITION` | note | stream | Only one rendition | | `OVER-TARGET` | error | stream | The live edge is further back than the budget allows | | `UNDER-TARGET` | note | stream | Inside the latency budget | | `INTERACTIVE` | note | stream | Close enough for people to talk over it | | `ORDINARY` | note | stream | An ordinary live latency | | `BROADCAST-LIKE` | warn | stream | Far enough back that a second screen gives it away | | `LATENCY-IS-THE-SEGMENT` | note | stream | The latency is the segment duration, multiplied | | `KEYFRAME-DOES-NOT-DIVIDE` | error | rendition | The keyframe interval does not divide the segment | | `KEYFRAME-DIVIDES` | note | rendition | The keyframe interval divides the segment cleanly | | `KEYFRAME-EQUALS-SEGMENT` | note | rendition | One keyframe per segment | | `KEYFRAME-TOO-FREQUENT` | warn | rendition | More keyframes than the segments need | | `OVERHEAD-GROSS` | warn | stream | The segment length is costing a lot of bitrate | | `OVERHEAD-NOTABLE` | note | stream | The segment length costs some bitrate | | `OVERHEAD-NEGLIGIBLE` | note | stream | The segment length costs almost no bitrate | | `HIGH-FPS-ABSORBS-IT` | note | stream | A high frame rate absorbs the overhead | | `SHORT-GOP` | warn | rendition | A very short group of pictures | | `RENDITIONS-MISALIGNED` | error | stream | The renditions cannot switch cleanly | | `RENDITIONS-ALIGNED` | note | stream | Every rendition is cut at the same instants | | `KEYFRAME-VARIES` | warn | stream | The rungs are not cut at the same keyframe spacing | | `FPS-VARIES` | warn | stream | The renditions do not share a frame rate | | `REQUEST-RATE` | note | stream | What this costs in requests | | `REQUESTS-BUSY` | warn | stream | The request rate is high | | `SEGMENT-BYTES` | note | rendition | What one segment weighs | | `LADDER-TOTAL` | note | stream | What the whole ladder costs to produce | | `THE-TRADE` | note | stream | One number, three consequences | ## What this page cannot do This page computes from the numbers on the sheet. It does not measure anything. - **The I-frame ratio is a model, not a measurement.** 10× a P-frame is ordinary for ordinary material; a static slide deck is far below it and confetti is far above. The overhead figures move with it, so treat them as the shape of the trade rather than a number to put in a budget. - **The latency formula is the protocol's floor, not a measurement of your stream.** `(buffer + 1) × segment` is what segmenting costs before the network, the encoder or the player's own start-up heuristics add anything. Real streams are further back, never closer. - **Low-latency variants change the formula.** LL-HLS and equivalents deliver partial segments, which decouples the live edge from the segment duration. If you are running one of those, the latency column here is the fallback path, not your path. - **No rendition is checked for whether its bitrate is right for its resolution.** This page has no opinion on the ladder's rungs, only on whether they can be cut and switched between. - Nothing here reaches the network, reads a manifest, or inspects a file. ## API `POST https://api.skillsafe.ai/v1/app-api/run` with a bearer token from https://segment-desk.skillsafe.ai/tokens.html. The body IS the input object — there is no `input` wrapper and no `X-App-Slug` header. `task` is required and must be one of plan, check, trade, ladder, deliver. `POST /estimate` is free and validates the same body. Full documentation at https://segment-desk.skillsafe.ai/api.html. ## Provenance Lanes derived from the `ffmpeg` skill in https://github.com/digitalsamba/claude-code-video-toolkit. The arithmetic, thresholds, sheet grammar and findings are this app's own. Not affiliated with or endorsed by the authors of that repository.