How big is a transparent video, and why does it take so long?
At 1080p and 30 fps, one second of transparent clip measured 230 MiB as MOV, 123 MiB as APNG and 43 MiB as MKV, against 0.22 MiB for the MP4 of the same frames. The size is not the surprising part — the lossless alpha formats simply refuse to throw pixels away. The time is: every frame is decoded, keyed pixel by pixel in JavaScript, written into the encoder as a PNG, and then encoded losslessly, and a ten-second 1080p MOV gets split into 38 batches that each run the encoder before the whole clip is encoded one more time to join them.
What one second actually weighs
These numbers are measured, not quoted from a spec sheet. The test clip is a noisy green screen with a single soft-edged subject moving across it, keyed and written out as an RGBA PNG sequence. Each container was then encoded with the exact argument list this tool hands to ffmpeg: -c:v qtrle -pix_fmt argb for MOV, -c:v ffv1 -pix_fmt yuva420p -level 3 -g 1 for MKV, -c:v apng -plays 0 for APNG, and libx264 at CRF 23 with -preset veryfast for MP4. The encoder was a desktop ffmpeg 9.0.1, not the WebAssembly build the browser runs.
At 1080p and 30 fps, one second of finished clip came out at 230 MiB as MOV, 123 MiB as APNG, 43 MiB as MKV and 0.22 MiB as MP4. At 720p the same second came out at 102, 55, 19 and 0.12 MiB.
Divide by pixels and the numbers stop moving: 3.88 bytes per pixel for MOV, 2.08 for APNG, 0.73 for MKV and 0.007 for MP4, at both resolutions. Size is therefore frames × width × height × that constant. Halve the long edge and you remove roughly three quarters of the file; drop 30 fps to 24 and you remove a fifth.
The APNG is worth a note because it comes out almost exactly the size of the PNGs that went into it — 246.9 MiB of output from 246.7 MiB of input frames at 1080p. An APNG is a PNG sequence in one file, so its size is predictable before you start, and it is also the slowest item on the list for the same reason: every frame gets compressed as a PNG for the second time.
Eight steps, once per frame
The export loop is not one encode. For every single frame it seeks the video element to that timestamp, draws the frame onto a canvas, reads the pixels back with getImageData, runs the keyer over the RGBA buffer, optionally runs the subject model and writes its mask into the alpha channel, puts the pixels back, composites a background if you asked for one, encodes the canvas to a PNG blob, and writes that blob into the encoder's filesystem.
Steps two to six are JavaScript over 2,073,600 pixels at 1080p, and 8,294,400 at 2160p. That is the part that scales with how long your clip is and cannot be handed to a codec, because the codec only ever sees finished frames. It is also the part that exists precisely because the work stays on your machine — there is no server doing it for you.
The intermediate has a cost of its own. The 1080p test clip wrote 123 MiB of PNG per second of finished video into the encoder before a single frame was encoded. Nobody asks for those files and every alpha export pays for them.
The 96 MB batch, and the second encode it forces
The encoder is given a memory budget rather than a frame count: about 96 MB of frames per batch, with every frame budgeted at width × height × 4 × 1.35 bytes to allow for RGBA plus PNG overhead. That works out at 8 frames per batch at 1080p, 20 at 720p and 2 at 2160p.
So ten seconds of 1080p at 30 fps — 300 frames — is 38 separate encoder runs, not one. Each run writes its PNGs, encodes them, reads the part back and deletes the PNGs. When there is more than one part, the parts are joined at the end, and for the alpha formats the join is not a stream copy: every part is decoded and the entire clip is encoded again with the same lossless settings. A ten-second 1080p MOV is encoded twice over, across 39 passes.
At 2160p the same ten seconds is 150 batches. That, rather than the bitrate, is why a 4K alpha export feels like it has hung — the batch count is doing the damage, and no amount of bandwidth changes it.
Where the clock goes
Encoder time on its own, measured on the desktop build: 2.9 seconds of CPU per second of 1080p MOV, 3.5 for MKV, 3.1 for MP4 — and 72 for APNG. That last figure is not a typo. On the same frames the PNG-based encoder needed roughly twenty-five times as long as the run-length one, which is why a short APNG export can take longer than a much larger MOV of the same clip.
None of those numbers include the per-frame keying, and all of them were measured on a native ffmpeg with the machine to itself. The browser runs the same encoder as single-threaded WebAssembly inside a tab that has a hard memory ceiling, so treat every figure here as a floor rather than a prediction of your own wall clock.
The progress bar is accidentally honest about this. It climbs to 45% while frames are keyed, then sits there through every batch encode and the join pass, then jumps to 100%. The last 55% of the work has no incremental progress to show.
The three dials that actually help
Long edge first. Going from 1080 to 720 on the long edge removes 56% of the pixels — 921,600 against 2,073,600 — and the file follows almost exactly: 230 MiB per second became 102.
Frame rate second. 24 fps instead of 30 is a fifth fewer frames, a fifth less keying and a fifth less file. If the shot is a static subject in front of a static screen, nothing about the alpha gets worse.
Format third, and only if you can accept the trade. MKV measured 43 MiB per second against MOV's 230, but it stores colour at half width and half height, so fine edges lose chroma detail even though the alpha is perfect. APNG is 123 MiB per second and plays in a browser tab or a deck with nothing installed, at the price of the slowest encode on the list.
Quality does nothing. That slider maps to a CRF value for H.264 and to nothing else. The three alpha formats are lossless and have nothing to trade.
Why it refuses instead of trying
Before anything runs, the tool multiplies frames × pixels × a per-pixel constant — 2.2 for MOV, 3.0 for MKV, 1.6 for APNG — and refuses if the answer is above 1.6 GB, because a browser tab cannot hold a two-gigabyte file on the WebAssembly heap. The message tells you to trim the clip, lower Long edge, or pick MP4 or GIF, in that order, because only the first two keep your alpha.
Against this test clip, qtrle measured 3.88 bytes per pixel, about 1.8 times its constant, while ffv1 measured 0.73 against a constant of 3.0. Both directions matter: a noisy clip can pass the check and still come out larger than the arithmetic predicted, and a very clean one can be refused when it would have fitted. The budget is a guardrail, not a quote. If an export dies at the very end, this is usually the reason — trim before you argue with it.
What the wait is not
It is not a slow upload, because nothing leaves the machine. It is not a queue, a server-side render or someone else's GPU you are waiting behind. And it is not your connection: the entire cost is frames × pixels on your own CPU, which is why a faster machine changes the answer and a faster network does not.
Related questions
Why is my transparent export hundreds of times bigger than the MP4 of the same clip?
H.264 predicts what you will not notice and discards it; the alpha formats are lossless and have to return every pixel exactly, including the partial alpha along a soft edge. Measured on the same keyed frames at 1080p30, that is 230 MiB per second of MOV against 0.22 MiB per second of MP4.
Does lowering the quality slider make it smaller or faster?
No. The slider maps to a CRF value for H.264 and to nothing else, so MOV, MKV and APNG ignore it completely — they are lossless and have no bits to give back. Change Long edge, frame rate or clip length instead.
Why does APNG take so much longer than MOV when the file is smaller?
Because every frame is compressed as a PNG again, on top of the PNG that was already written to hand it to the encoder. Measured on the desktop build, APNG needed about 72 seconds of encode per second of 1080p clip, against 2.9 for MOV — roughly twenty-five times longer.
The progress bar sits at 45% for ages. Is it stuck?
No. Keying finished at that point; what is left is one encoder run per batch plus the join pass, and none of that reports incremental progress. On a ten-second 1080p MOV that is 38 batch encodes and one full re-encode of the clip.