How long video transcoding takes

Read the real latency breakdown from 1,770 completed jobs. The encode ran a median 861 ms while waiting to start took 3,626 ms, which is 57% of total time.

Share

Short version

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

StepJobsMedian90thSlowest
Waiting to start1,7703,626 ms21,966 msvery long
Download the input1,44969 ms653 ms15,812 ms
The FFmpeg encode1,272861 ms3,886 ms110,103 ms
Upload the output1,430578 ms1,644 ms82,646 ms
Probe metadata200171 ms411 ms4,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 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.

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. For what those jobs cost, see FFmpeg API pricing compared. For why jobs fail before they get this far, see common FFmpeg errors and what they mean.

Frequently asked questions

How long does it take to transcode a video?

The encode itself is usually the fast part. Across 1,770 real jobs on short clips the FFmpeg step had a median of 861 ms and a 90th percentile of 3,886 ms. Total wall-clock was dominated by waiting to start, at a median of 3,626 ms.

Why is my video API slower than running FFmpeg locally?

Because you are paying for scheduling and transfer that a local run does not have. In our data the queue wait was 57.1% of total time at the median, with download and upload adding another 647 ms. The encode was the smallest share.

Is upload or download the bigger cost in a video pipeline?

Upload, by a wide margin. Fetching the input had a median of 69 ms while returning the output had a median of 578 ms, roughly 8 times slower, because the output is usually larger and writing to storage costs more than reading from a CDN.

How fast is ffprobe compared to encoding?

A probe had a median of 171 ms against a median encode of 861 ms, so reading metadata costs about a fifth of an encode. It reads a header rather than decoding, which is why the gap holds regardless of file length.

What makes video transcoding slow?

Three things in order: waiting for capacity, the size of the output you are writing back, and only then the encode. Preset and CRF change the encode, which was the smallest of the three in our data on short clips.

Sources

Tags #ffmpeg#performance#latency#transcoding
All posts
Share
  1. Opus vs AAC vs MP3 vs FLAC Engineering blog
  2. AV1 vs H.264 VMAF compared Engineering blog
  3. AV1 vs VP9 vs HEVC vs H.264 Engineering blog