# Describe Desk > Audio description goes in the silences between dialogue. This works out where > those silences are, what each one holds in words, which descriptions fit, and > how long after the thing it describes each one actually arrives. A gap is a word budget, and it is smaller than it looks. ## The one thing to know ```text words = floor((gap - 2 x handle) x rate) ``` At 3 words a second with 0.2 s of handle at each end: | Silence | Usable | Holds | | --- | --- | --- | | 0.5 s | 0.10 s | 0 words | | 1 s | 0.60 s | 1 word | | 2 s | 1.60 s | 4 words | | 3 s | 2.60 s | 7 words | | 5 s | 4.60 s | 13 words | | 10 s | 9.60 s | 28 words | | 20 s | 19.60 s | 58 words | The handles come off **every** gap regardless of its length. So a short silence is not a small budget — it is no budget, and **twenty half-second gaps carry 0 words between them**. That is why a programme can look full of pauses and have almost nothing describable in it. And what needs describing happens **while somebody is talking**. The action, the entrance, the caption land during dialogue, and the first place anybody is allowed to speak is afterwards. Description is structurally late; the only question is by how much, and past about 8 seconds it is no longer about what is on screen. Which means **a surplus in the wrong place is not a surplus**. A programme can have 2.6 times the room it needs and still deliver five of its seven descriptions late — two of them by more than a minute — because all the silence is in the tail. ## What it is A single page at https://describe-desk.skillsafe.ai. The engine that finds the gaps and places the notes runs entirely in your browser, needs no account and costs nothing. Writing the report calls a model and needs credits. ## The free engine Everything below is computed client-side in `describe.js` and sent with every run as `prescan`, so the model is never asked to recompute it: - **Gaps.** Every silence between dialogue cues, plus the head gap before the first line and the tail gap after the last. The tail gap only exists if a runtime is stated, and it is frequently the longest silence in the programme. - **What each holds.** `seconds`, `usable = max(0, seconds - 2 x handle)`, and `words = floor(usable x rate)`. - **The budget.** Total room against total demand, the shortfall or spare, and how many silences hold nothing at all. - **Placement.** Each note goes in the first gap at or after its moment that still has room, in time order. Greedy, not optimal. - **Lag.** For every placed note, the seconds between its moment and the moment it starts being spoken. - **Extended pause cost.** `words / rate + 2 x handle` — the runtime a pause has to manufacture. Being 40 words short at 3 a second is 13.73 s added to the programme. The engine makes no network calls. ## Sheet grammar Three blocks. Blank lines and `#` comments are ignored. ```text PROGRAMME name | the museum film duration | 2:30 rate | 3 handle | 0.2 DIALOGUE d1 | 0:04.0 | 0:19.5 | welcome to the east wing d2 | 0:20.4 | 0:33.0 | this head was cast in the fifteenth century NOTES n1 | 0:01.0 | a dark gallery, one bronze head lit from above | 9 n2 | 0:19.8 | the camera pushes in slowly on the face ``` - A dialogue row is `id | start | end | what is said`. - A note row is `id | moment | what to say | words`. **The word count is optional** — left off, the words in the text are counted. - Times may be seconds (`19.5`), `m:ss.s` (`0:19.5`) or SRT timecode (`00:00:19,500`), because the input to this page is a transcript. - `rate` is words a **second**, not a minute. 3 is 180 a minute. - `handle` is subtracted **twice** from every gap. - `duration` is what creates the tail gap. Without a runtime it does not exist. - `rate` and `handle` both have defaults, both multiply every figure, and an assumed one is reported as assumed. - A sheet with no dialogue is valid, and so is one with no notes. ## Lanes | Lane | What it decides | Fields | | --- | --- | --- | | `plan` | The description before the cut is locked | `brief`, `known` | | `check` | What fits in the silences you have | `sheet`, `symptom` | | `gaps` | Where the silences are and what each one holds | `sheet`, `shape` | | `notes` | Which descriptions land and which arrive late | `sheet`, `matters` | | `deliver` | What gets cut, moved or paused for | `sheet`, `fixed` | `check` is the primary lane. Every lane ships a worked example that costs nothing to read. ## Severity Severity is fixed by the code, not by the model. **Errors are reserved for a description that cannot be delivered usefully at all** — nowhere to put it, longer than any silence in the programme, or so late it is about something that has gone. A real cost that needs a decision is a warning. A description of the material is a note. There are 24 codes. `BUDGET-SHORT`, `NOTE-UNPLACED`, `NOTE-TOO-LONG`, `NOTE-VERY-LATE`, `NOTE-OUTSIDE`, `WALL-TO-WALL`, `CUES-OVERLAP` are errors. `GAP-GENEROUS`, `HEAD-GAP`, `TAIL-GAP`, `NOTE-FITS`, `BUDGET-AMPLE` and the rest of the descriptive ones are notes. ## API ``` POST https://api.skillsafe.ai/v1/app-api/run X-App-Key: Content-Type: application/json {"task": "check", "sheet": "PROGRAMME\nduration | 2:30\n\nDIALOGUE\n...", "symptom": "everything arrives late"} ``` The run body **is** the input object. There is no `input` wrapper. Every field is a string. Full documentation: https://describe-desk.skillsafe.ai/api.html ## What this page cannot do - **It has not heard a word of the programme.** - **It does not know what is worth saying.** Every note is a word count at a moment; whether a listener needs it is a judgement about the film. - **The placement is greedy, in time order**, and is not optimal. A note that could only fit by displacing an earlier one is a decision, not a computation. - **The rate is one number standing in for a performance.** - **Word counts are a proxy for duration.** Long words take longer, and a tight gap has one real test, which is reading it aloud against the picture. - **It cannot see that two notes describe the same thing**, or that the dialogue already covers one — which is the most common way a shortfall actually gets solved. ## Source Lanes derived from the `openai-whisper` skill in https://github.com/openclaw/openclaw, which transcribes audio locally and can write SRT — a transcript with timings. Those timings are the input to the only question audio description really asks: not what to say, but when anybody is allowed to say it. Not affiliated with or endorsed by that repository's authors.