# How long video transcoding takes

Canonical: https://rendobar.com/blog/video-transcoding-time/
Author: Abdelrahman Essawy
Published: 2026-08-20
Updated: 2026-08-20

---

## Key takeaways

- Across 1,770 completed jobs the FFmpeg encode itself had a median of 861 ms while the wait to start had a median of 3,626 ms.
- Queueing is 57.1% of total job time at the median and 94.5% at the 90th percentile. The encode is the fastest part of the pipeline.
- Upload is 8x slower than download: 578 ms against 69 ms at the median, which is 67% of the median encode time to hand the result back.
- The encode has the widest tail of any step: median 861 ms, 90th percentile 3,886 ms, slowest single run 110,103 ms.
- A metadata probe is the fastest thing in the system at a median of 171 ms, which is why it belongs in front of every job.

## Short version

Everyone optimises the encode. In 1,770 completed jobs, **the encode was the fastest part of the pipeline.**

| Step | Jobs | Median | 90th | Slowest |
|---|---|---|---|---|
| Waiting to start | 1,770 | **3,626 ms** | 21,966 ms | very long |
| Download the input | 1,449 | 69 ms | 653 ms | 15,812 ms |
| **The FFmpeg encode** | 1,272 | **861 ms** | 3,886 ms | 110,103 ms |
| Upload the output | 1,430 | 578 ms | 1,644 ms | 82,646 ms |
| Probe metadata | 200 | 171 ms | 411 ms | 4,367 ms |

Waiting to start had a median of **3,626 ms**, more than four times the encode. Measured as a share of each job's own total, queueing was **57.1% of the time at the median and 94.5% at the 90th percentile**.

So on a typical short clip, more than half the time is spent before any work begins, and on a bad day almost all of it is.

## Why the queue dominates

Nothing is running yet during that window. The job has been accepted, credits have been checked, and it is waiting for capacity to pick it up.

That wait is not proportional to the work. A five-second clip and a five-minute one queue the same way, which is why the queue share is worst on exactly the jobs people expect to be fast. A 200 ms encode behind a 3.6 second wait is a 5% efficient pipeline, and no amount of preset tuning changes that ratio.

The distribution is also very skewed. The 10th percentile wait was **629 ms** and the 99th was **119,886 ms**, roughly two minutes. Medians describe the common case here and averages do not.

The practical consequence is about concurrency rather than speed. If you have a hundred clips to process, submitting them together and letting them queue in parallel finishes far sooner than optimising any single one, because you pay the wait once across the batch instead of once per clip in series.

## Upload costs eight times what download does

**Download had a median of 69 ms. Upload had a median of 578 ms.**

That asymmetry is not a surprise once you look at what each step does, but the size of it is worth internalising. Fetching an input pulls a file from a CDN edge that is optimised for reads. Writing an output puts a usually larger file into object storage, which is a different and slower operation.

At the median, **returning the result costs 67% of what producing it cost.** For a pipeline that produces many small outputs, that is the second-largest line item in the whole system and it is entirely invisible if you only benchmark FFmpeg.

The lever is output size rather than throughput. Anything that makes the output smaller (a higher CRF, a better codec, a smaller resolution) shortens the upload proportionally, which means encoder settings affect total latency twice: once through the encode and once through the transfer.

## The encode has the widest tail

The FFmpeg step is fast in the common case and occasionally very slow. Median **861 ms**, 90th percentile **3,886 ms**, slowest single run **110,103 ms**. That is a 128x spread between median and worst.

Two things drive it. Longer or larger inputs do more work, which is expected. But the second cause is the one that catches people out, which is that **x264 with `-threads auto` sizes itself to whatever the machine has free**, so identical work on a busy machine takes far longer than on an idle one. We measured that separately and pinned threads moved run-to-run variance from 85% down to between 1.4% and 8.9%.

This is why we do not publish timing conclusions from a single run. A 40% difference between two encoder settings, measured once, is inside the noise of the machine rather than a property of the settings. [Benchmark variance in FFmpeg measurements](/blog/measurement-noise-ffmpeg-benchmarks/) has the full experiment.

Sizes, by contrast, are exact. The same command produced byte-identical output on all ten runs we tested, so a size comparison needs one run and a timing comparison needs many.

## The probe is the cheapest thing in the system

At a median of **171 ms**, reading metadata costs about a fifth of a median encode and roughly a twentieth of the median queue wait.

That ratio is the argument for probing before processing. It is fast enough to disappear inside the wait you were already paying, and it eliminates the largest single cause of failed jobs, which is an input that was never going to load. In our failure analysis, **61 of 208 failures were an unreachable input** against 46 for a bad command.

Probing also bills a flat **$0.0010** against a median FFmpeg job of **$0.0025**, so it is cheap in both dimensions.

## What to do with this

**Batch and parallelise before you tune.** The queue is paid per job and it is over half the median job. Ten jobs submitted together beat ten jobs optimised individually and run in series.

**Optimise output size, not just encode speed.** It shortens the upload too, and upload is the second-largest step. This compounds across an ABR ladder, where [the top rung alone costs more than the other four combined](/blog/transcode-ladder-cost/).

**Do not micro-tune the preset for latency on short clips.** The encode is 861 ms at the median. Even halving it moves total time by a fraction of what one queue wait costs.

**Probe first.** 171 ms to avoid paying for a job that cannot succeed.

**Pin threads if you are benchmarking.** Otherwise you are measuring the machine's mood.

## Where this stops

These are short clips. The archive is dominated by a 5.013 second sample, and the balance shifts completely on long-form video, where the encode grows linearly while the queue wait does not. On a ten-minute source the encode would dominate and most of the advice above inverts.

Timings carry real production variance because they are real production runs across five months on shared infrastructure, not a controlled benchmark. Treat the medians as representative of this workload and the tails as evidence that tails exist.

The queue figure is measured from job creation to execution start, so it includes admission, credit checks, dispatch and scheduling as one number. We have not broken it down further here, and a breakdown would name infrastructure we do not publish.

None of this measures cold-start behaviour separately, which is a known contributor to the slowest waits and deserves its own measurement rather than an inference from this one.

For per-setting encode numbers, see [FFmpeg encoding settings measured](/blog/ffmpeg-encoding-settings/). For what those jobs cost, see [FFmpeg API pricing compared](/blog/ffmpeg-api-pricing-compared/). For why jobs fail before they get this far, see [common FFmpeg errors and what they mean](/blog/ffmpeg-errors-explained/).
