Proxies
A proxy is a low-resolution copy of a clip that the viewport uses in place of the original, so that heavy footage scrubs at a usable rate. Output never sees it.
Why they exist
Random access is what makes 4K slow. To show frame n of a long-GOP clip the decoder has to go back to the previous keyframe and decode forward, and that work scales with the picture size and with how far back the keyframe is. Jumping around a 4K H.264 or HEVC clip therefore costs far more than the same jump in a 1080p copy, however fast the GPU that draws the result.
The engine decodes footage itself, with the GPU’s hardware decoder where there
is one, and cached playback holds full rate once frames are cached. A proxy is
for the case those do not cover: heavy footage you need to scrub freely before
anything is cached. A proxy is smaller, and it is encoded with a short GOP
(-g 12), so a seek never has far to go back.
Earlier versions of this page quoted a table of seek and upload timings. It was measured in Chromium’s video decoder, which no longer decodes your footage, so it has been removed rather than left to mislead. Whether a proxy helps on your machine is a question the viewport’s performance HUD answers in a few seconds.
The safety property
A proxy is substituted for the interactive viewport only. Never for output.
That is enforced by polarity rather than by vigilance. Substitution is something the interactive viewport asks for; the export, the Render Queue and the command line never ask for it, so they reach the original footage by doing nothing. There is no opt-out to forget.
Substitution is pixels only, at a single chokepoint. Size, duration, frame rate, pixel aspect, alpha interpretation, loop count, trim, slip, stretch and time remap all keep reading the original asset. There is no second record to keep in step, so a proxy cannot drift out of alignment with its source.
Using one
The proxy row lives on the asset, next to Interpret Footage ▸ Alpha — the same shape of thing, because the record belongs to the file. One proxy therefore speeds up every layer using that file, in every composition.
The row always states which state the file is in, because a proxy silently in use looks like a quality bug:
| State | Meaning |
|---|---|
| Full resolution | No proxy. The row still says what one would be — 1920 × 1080 for a 4K source — so the action is a known quantity before you click it |
| Generating | An ffmpeg job is running. The asset renders at full resolution meanwhile |
| Ready | A decodable stand-in exists |
| In use | Ready, and the global switch is on. Styled loudly rather than left to be inferred from how soft the picture looks |
| Failed | Generation ran and failed, or the file went missing. The error says why, and renders fall back to full resolution |
The global switch — proxies on or off for the whole project — is repeated on the row rather than buried in a menu.
Generating, attaching, detaching
Generate runs ffmpeg as a child process, outside the interface, for the same reason the export encode does: the transcode must not compete with the UI, because the whole promise is that the asset stays usable at full resolution while it runs. The call returns as soon as the job is queued — import is never blocked. It uses the same ffmpeg as export, which every installer ships — see ffmpeg & codecs.
The target is a halved long edge, at or below 1920, rounded to even dimensions. Alpha sources become VP9 WebM; everything else becomes H.264 MP4.
Cancel is real, not cooperative: the child process is killed. Quitting kills
any survivors, which is the other half of why a generating record is never
persisted — there would be no process behind it after a reload.
Attach points the record at a file you supply yourself. It needs no ffmpeg,
which is the route when ffmpeg is not available (a build from source with none on
PATH, say). Detach removes the proxy record, and
deliberately does not delete a file you attached.
Every failure path lands the asset back at full resolution rather than in an error state. A failed proxy is a missed optimisation; a broken asset is a lost shot. The enumerated cases: no ffmpeg, encode error, a throwing bridge, an unreadable original, empty output, cancellation, an asset deleted mid-encode, and an asset re-imported mid-encode — where the stale job re-reads the record after every await and stands down rather than overwriting the new one.
When it refuses, and why
Refusals are explained rather than attempted, and the check is pure — so the UI can disable the action and say why without starting anything.
| Reason | Message |
|---|---|
| No ffmpeg | Proxies need ffmpeg, which this build cannot reach. You can still attach one |
| Not video | Only video footage can have a proxy |
| Too small | This footage is already small enough to scrub smoothly |
| Unknown size | This file’s dimensions are unknown, so no proxy size can be chosen |
| Already running | A proxy is already being generated for this file |
| Source unreadable | The original file could not be read |
“Too small” means a long edge at or below 1280. Below that the source is already small enough to scrub smoothly, so halving it would buy little and cost the disk and the wait.