# Offload Desk > Cards buy time, not throughput. A shooting day is a queue: storage fills at > `duty × data rate` and drains at `offload / passes`, and if the fill wins the day is > not sustainable — no number of cards makes it so. Two bodies, seven cards and 954 GiB fill at 144 MB/s against a 100 MB/s drain, > so the whole pool is gone 6.5 h into a 10-hour day. Doubling the cards moves that to 13 h and changes the > deficit not at all. What fixes it is 288 MB/s of pipe, or rolling 34.8% of the time. > And there are TWO questions here: the same day can pass on rate and still need 5.6 hours > of copying in the 2 hours after wrap. ## The one thing to know **CARDS BUY TIME, NOT THROUGHPUT.** ```text fill duty × summed data rate passes copies + (1 if verify) drain offload rate / passes deficit fill - drain run out after total capacity / deficit the day makes fill × hours copy hours bytes × passes / offload ``` Capacity appears in exactly one of those lines, and it is the line about WHEN rather than the line about WHETHER. On a deficit day the card count sets the length of the runway and nothing else, which is why "bring another card" is the standard answer to a problem it cannot touch. Two smaller facts fall out of the same arithmetic: a printed card holds 6.87% less than it says, on every card ever made; and a card's SUSTAINED WRITE must exceed the data rate or the camera drops frames, which is a separate failure that capacity cannot buy its way out of either. ## More cards, same deficit | Cards | Pool | Runs out after | Sustainable | | --- | --- | --- | --- | | 2 × 160 GB | 298 GiB | 2.8 h | **no** | | 4 × 160 GB | 596 GiB | 5.7 h | **no** | | 8 × 160 GB | 1.16 TiB | 11 h | **no** | | 16 × 160 GB | 2.33 TiB | 23 h | **no** | | 64 × 160 GB | 9.31 TiB | 3.8 days | **no** | A 1.5 Gb/s camera at a 70% duty fills at 131 MB/s. A 200 MB/s pipe making two copies drains 100 MB/s. The deficit is 31.2 MB/s and it does not care how many cards there are. **Sixty-four cards is 9.31 TiB and 3.8 days — which is not a solution, it is a longer runway.** Cards are a buffer, not a pipe. The last column is the one that matters and nothing in the first column changes it. What DOES change it: the offload has to reach 262 MB/s (1.31× the pipe), or the duty has to come down from 70% to 53.3%, or the copy count has to drop — and that last one is redundancy rather than throughput. ## Copies and the verify pass | Copies | Verify | Passes | Effective drain | Duty it supports on a 1.5 Gb/s camera | | --- | --- | --- | --- | --- | | 1 | no | 1 | **500 MB/s** | all of it, with 2.67× to spare | | 2 | no | 2 | **250 MB/s** | all of it, with 1.33× to spare | | 2 | yes | 3 | **167 MB/s** | 88.9% | | 3 | yes | 4 | **125 MB/s** | 66.7% | The same 500 MB/s pipe, four ways. **Every byte is written once per copy and read once more to verify**, so the number that belongs in the queue is the pipe divided by the passes — and the pipe is what gets quoted. Two copies and a verify is the smallest responsible configuration and it is THREE passes: a 500 MB/s pipe becomes 167 MB/s of card drained. Anybody planning with the headline figure is out by a factor of three. ## The two questions, side by side | Duty | Fill | Drain (2 copies) | Rate question | 10 h produces | Copying it twice | Duration question against 2 h | | --- | --- | --- | --- | --- | --- | --- | | 10% | 18.8 MB/s | 100 MB/s | passes | 629 GiB | 1.9 hours | passes | | 20% | 37.5 MB/s | 100 MB/s | passes | 1.23 TiB | 3.8 hours | **fails** | | 30% | 56.3 MB/s | 100 MB/s | passes | 1.84 TiB | 5.6 hours | **fails** | | 50% | 93.8 MB/s | 100 MB/s | passes | 3.07 TiB | 9.4 hours | **fails** | **Read the two verdict columns against each other.** At a 20% duty the rate question passes and the duration question fails: the pipeline keeps up perfectly well and there is still 3.8 hours of copying to do in two hours. They are different questions. The rate question asks whether the pipeline can keep up WHILE IT RUNS, and it only binds if the offload runs alongside the shoot. The duration question asks whether the copying fits in the time available, and it binds when the offload waits for wrap. A day can fail either, both, or neither. ## Decimal on the box, binary in the filesystem | The box says | It actually holds | Short by | | --- | --- | --- | | 64 GB | **60 GiB** | 4.4 GiB | | 128 GB | **119 GiB** | 8.8 GiB | | 256 GB | **238 GiB** | 18 GiB | | 512 GB | **477 GiB** | 35 GiB | | 1024 GB | **954 GiB** | 70 GiB | Manufacturers count in decimal (1 GB = 1,000³ bytes) and filesystems report in binary (1 GiB = 1,024³). The ratio is fixed, so the shortfall is **6.87% on every card ever made** — not a rounding difference and not the manufacturer cheating, just two units sharing an abbreviation. It matters here because a plan built on the printed numbers is 6.87% short before anything else goes wrong, and 6.87% of a 4.1 TB card order is 262 GiB. ## Thresholds | Threshold | Value | What it separates | | --- | --- | --- | | a card fast enough | sustained write ≥ the data rate | below it the camera drops frames, whatever the capacity. | | a card comfortably fast | ≥ 1.25× the data rate | a spec figure is a best case on a fresh card in a lab. | | a thin throughput margin | under 15% of the fill | inside the error on a guessed duty cycle. | | the unit shortfall | 6.87% | fixed, on every card ever made — decimal on the box, binary in the filesystem. | Defaults when the sheet is silent: 10 hours, a 30% duty cycle, 200 MB/s of offload, 2 copies, no verify, offload running alongside the shoot, and 2 hours after wrap. The duty cycle and the offload throughput are reported as WARNINGS when assumed, because they are the two sides of the only comparison that matters. ## Sheet grammar Two blocks. `DAY` is `key | value`, one per line. `CAMERAS` is a table. ``` DAY name | what this day is hours | 10 how long the shooting day is duty | 50% fraction of it actually rolling - or 0.5, or 1/2 offload | 200 MB/s the SLOWER of the reader and the destination copies | 2 how many copies each byte gets verify | yes re-read everything to check it (costs another pass) concurrent | yes does the offload run during the shoot, or only at wrap? tail | 2 hours available after wrap, if it is not concurrent CAMERAS c1 | the A camera | 1500 Mb/s | 4 x 160 GB | 800 MB/s | c2 | the B camera | 800 Mb/s | 3 x 128 GB | 500 MB/s | ``` A CAMERAS row is `id | what it is | data rate | cards | card write | why`. **Mind the units, because the two columns use different conventions and they differ by a factor of eight.** A bare number in the DATA RATE column is MEGABITS a second, because that is how cameras are quoted (`1500`, `1500 Mb/s` and `1.5 Gb/s` are the same). A bare number in the card-write and offload columns is MEGABYTES a second, because that is how storage is quoted (`800`, `800 MB/s`). Getting those two the wrong way round is an eightfold error and it is the commonest mistake on a media plan. The cards column takes `4 x 160 GB`, `512GB` or `2x512` — a count and a printed size. **Printed sizes are decimal**, so the page reports the binary figure alongside, which is 6.87% smaller and is what will actually appear on the drive. `concurrent` is the setting that decides which of the two questions binds. With it on, the pipeline has the whole day to work in and the RATE comparison is what matters. With it off, the whole day's footage arrives at wrap and the DURATION is what matters. ## Lanes - **`plan`** — Size the pipe before counting the cards. A media plan gets made by counting cards, which answers a question nobody asked. This starts from the rate the day fills storage and the rate the pipeline drains it, sizes the offload to carry the copies it actually has to make, and only then works out how many cards buy a comfortable buffer. Sections: Summary, The Sheet, The Setting, Reasoning, Next Step. - **`check`** (primary) — Whether this day survives its own footage. The paid read of what the free panel computes. What the day fills at, what it drains at, whether that is a deficit, when the cards run out if it is, what the day produces in total, and how long copying it takes — which is a different question with a different answer. Sections: Summary, Verdict, Findings, Corrected Sheet, Next Step. - **`rate`** — The rate question: does the pipeline keep up. Fill against drain, and what each side is made of. Includes the two inverse questions worth asking on the floor — the offload throughput this day needs, and the duty cycle the pipeline you have can actually support — and says plainly when more cards cannot help. Sections: Summary, What Fills, What Drains, Where The Cards Come In, Next Step. - **`duration`** — The duration question: does the copy fit. A day can pass the rate question and still fail this one. Total bytes times passes over the throughput, in hours, against the hours there actually are — and the answer changes completely depending on whether the offload runs alongside the shoot or waits for wrap. Sections: Summary, What The Day Produces, What Copying Costs, Against The Clock, Next Step. - **`deliver`** — Decide what changes: the pipe, the day, or the expectation. Sorts every finding into what a faster pipe fixes, what only a shorter or less busy day fixes, and what nothing fixes. More cards appear in none of those buckets, which is the point — they change when you run out and never whether you do. Sections: Summary, A Faster Pipe Fixes, Only A Smaller Day Fixes, Nothing Fixes, Next Step. ## Findings All 31 are computed in the browser and cost nothing. | Code | Severity | Scope | What it means | | --- | --- | --- | --- | | `HOURS-ASSUMED` | note | day | The length of the day was assumed | | `DUTY-ASSUMED` | warn | day | The duty cycle was assumed | | `OFFLOAD-ASSUMED` | warn | day | The offload throughput was assumed | | `TAIL-ASSUMED` | warn | day | The time after wrap was assumed | | `CONCURRENT-ASSUMED` | warn | day | Whether the offload runs during the shoot was assumed | | `COPIES-ASSUMED` | note | day | The number of copies was assumed | | `ONE-COPY` | warn | day | Only one copy is being made | | `NO-CAMERAS` | warn | day | A day, and nothing recording | | `GB-IS-NOT-GIB` | note | day | The cards are smaller than the box says | | `CARD-TOO-SLOW` | error | camera | This card cannot be written fast enough | | `CARD-WRITE-THIN` | warn | camera | This card's write margin is thin | | `CARD-WRITE-FINE` | note | camera | This card is comfortably fast enough | | `RECORD-TIME` | note | camera | How long one card holds this camera | | `POOL-TIME` | note | camera | How long this camera's whole card pool holds | | `CAMERA-SHARE` | note | camera | What share of the fill this camera is | | `THE-RATES` | note | day | What fills and what drains | | `SUSTAINABLE` | note | day | The pipeline keeps up while it runs | | `NOT-SUSTAINABLE` | error | day | The pipeline cannot keep up | | `CARDS-BUY-TIME-NOT-THROUGHPUT` | warn | day | More cards would not fix this | | `TIME-TO-RUN-OUT` | warn | day | When the cards run out | | `MARGIN-THIN` | warn | day | The pipeline only just keeps up | | `OFFLOAD-NEEDED` | note | day | The offload throughput this day actually needs | | `DUTY-AFFORDABLE` | note | day | The duty cycle this pipeline can support | | `THE-DAY-PRODUCES` | note | day | What the day produces | | `COPY-HOURS` | note | day | How long copying the day takes | | `COPY-EXCEEDS-THE-TAIL` | error | day | The copy does not fit in the time after wrap | | `COPY-FITS` | note | day | The copy fits in the time after wrap | | `CONCURRENT` | note | day | The offload runs alongside the shoot | | `SEQUENTIAL` | warn | day | The offload only starts after wrap | | `VERIFY-COSTS-A-PASS` | note | day | The verify pass costs as much as a copy | | `COPIES-DIVIDE-THE-PIPE` | note | day | Each copy divides the effective throughput | ## What this page cannot do This page computes from the numbers on the sheet. It has not measured anything. - **The duty cycle is the weakest input and it multiplies straight into everything.** Nobody measures it. A figure taken from how the day felt is easily out by half, and half the fill rate is a different day entirely. - **The offload figure should be the SLOWER of the reader and the destination**, under load, on the bus it will actually share. A headline number from either box is a best case that a real copy will not see. - **This is a steady-state model.** A real day is lumpy: nothing rolls for an hour, then three cards arrive at once. The averages are right and the queue is bumpier than they suggest, which makes a thin margin thinner than it looks. - **Copying is treated as sequential passes at one rate.** Writing two destinations at once can beat that if the bus has the headroom, and it can be slower if it does not. The model here is the pessimistic reading and the honest default. - **Nothing here models the actual codec.** A data rate quoted for a codec is a nominal figure and variable-bitrate material moves around it; on some formats a static frame costs a fraction of a busy one. - **Card capacity is treated as fully usable.** Filesystem overhead, a reserve the camera keeps, and a card you should never fill to the last byte all make the real figure smaller than the binary one. - Nothing here reaches the network, reads a file, or inspects any media. ## API `POST https://api.skillsafe.ai/v1/app-api/run` with a bearer token from https://offload-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, rate, duration, deliver. `POST /estimate` is free and validates the same body. Full documentation at https://offload-desk.skillsafe.ai/api.html. ## Provenance Lanes derived from the `video-frames` skill in https://github.com/steipete/clawdis. The arithmetic, thresholds, sheet grammar and findings are this app's own. Not affiliated with or endorsed by the authors of that repository.