When compressing a video would make it bigger

See how a compression job spots that re-encoding would grow an efficient file and returns the original, and how it reports a size target it cannot reach.

Share

Re-encoding a video that is already efficiently encoded can make it bigger, and a compressor that always encodes will hand you the bigger file without saying so. Rendobar’s compress.target job checks first. Against one well-encoded 343.9 KB clip, the quality-first postures that could not beat the original returned it untouched, and the impossible size targets returned the smallest file the source allows with a low verdict. Both decisions still ran probe encodes and were billed.

For the how-to side (commands, the bitrate formula and its failure mode), see how to compress video to a target size. The shared clip and setup are on how we benchmark.

Four delivery postures against the same source. Three concluded that re-encoding was not worth doing and passed the original through.
CaseVerdictCodecVMAFSizeProbes
visually-losslesspassthroughh26496.3 343.9 KB3
balancedpassthroughh26493.3 343.9 KB5
efficientacceptableh26489.0 295.1 KB5
archivepassthroughh26496.3 343.9 KB3
Measured 2026-08-20 with the compress.target job type. VMAF is scored by the job against the original while it searches. Across all 17 cases the search ran 92 probe encodes for $0.260989.

Updated 20 September 2026. Two things on this page changed after it was measured, and the numbers below are left as they were recorded. The video tiers moved from VMAF 96, 93 and 88 to 94, 91 and 86, because the scores come from the NEG model, which reads about two points under the scale those numbers were quoted on. And a dry run now returns the verdict the real run would give, so the balanced case below reports skipped_no_improvement instead of a predicted 371.8 KB. The changelog entry has the detail.

The passthrough verdict

Three of the seventeen cases returned passthrough. Two of them ask the same question: archive is visually-lossless with for: "archive" in place of for: "web", and it gave the same answer. So there are two distinct refusals, visually-lossless and balanced.

The job reached them by trying. It ran three to five probe encodes, scored each against the source, found that meeting the quality target would take more bytes than the original already spends, and handed the original back. That search cost about a cent per case where the cost was recorded.

Only efficient, the posture that accepts lower quality, compressed: 295.1 KB at VMAF 89.0, a 14% saving.

A pipeline that re-encodes everything on upload will, on already-optimised files, pay to make them larger and worse. Neither loss is visible, because the file still plays.

Here is the request, and the fields that say it passed through:

job.ts
import { createClient } from "@rendobar/sdk";
const rb = createClient({ apiKey: process.env.RENDOBAR_API_KEY });
const job = await rb.jobs.run({
type: "compress.target",
inputs: { source: "https://cdn.rendobar.com/assets/examples/sample.mp4" },
params: { target: "balanced", for: "web" },
});
const d = job.output.data;
// On this source: "passthrough", "skipped_no_improvement", 5 probes.
console.log(d.verdict, d.status, d.probes, job.cost?.formatted);

Install with npm i @rendobar/sdk. jobs.run() submits and waits, so it returns the finished job in one call.

terminal
curl -X POST https://api.rendobar.com/jobs -H "Authorization: Bearer $RENDOBAR_API_KEY" -H "Content-Type: application/json" -d '{
"type": "compress.target",
"inputs": { "source": "https://cdn.rendobar.com/assets/examples/sample.mp4" },
"params": { "target": "balanced", "for": "web" }
}'

Returns immediately with a job id. Poll GET /jobs/{id} or register a webhook rather than blocking on the request.

dryRun: true runs the search and returns the predicted size, quality and verdict without producing or storing an output file.

CaseDry runReal runDry run costReal run cost
150 KB ceiling146.5 KB, VMAF 64.3146.5 KB, VMAF 64.3$0.016$0.013
balanced371.8 KB encodepassthrough at 343.9 KB$0.016$0.012

On the byte target the two matched to the byte. The match shows reproducibility, not foresight: the search is deterministic, so running it twice gives the same answer.

On balanced they disagreed. The dry run returned the encode it would have produced, 371.8 KB, and the real run passed the original through. The first version of this post called the dry run “right, twice”, reading the 371.8 KB as a prediction that re-encoding would grow the file. That was generous. A dry run that reports an encode the real run would never ship is not predicting the result, and the update above is the fix: it now returns the same skipped_no_improvement verdict the real run gives.

The first version also said a dry run answers “what would this cost me” without paying for the encode. It does not. The dry run is billed for the search it runs, so it costs about the same as the real run. Four identical searches on this file billed between $0.013 and $0.017, which covers both columns above. What it saves is the output file, not the compute.

effort: fast is not a small compromise

Same 150 KB ceiling, three effort levels. The search quality changes what quality fits in the budget.
CaseVerdictCodecVMAFSizeProbes
effort fastlowh26447.4 142.2 KB6
effort balancedlowh26464.3 146.5 KB6
effort thoroughlowh26466.1 147.8 KB6
Measured 2026-08-20 with the compress.target job type. VMAF is scored by the job against the original while it searches. Across all 17 cases the search ran 92 probe encodes for $0.260989.

At the same budget, fast scored about 17 VMAF points below balanced, and thorough bought back about 2. The curve is steep at the cheap end and flat at the expensive end. I would not use fast for anything people will watch, and I would only pay for thorough on content that will be watched many times.

The floor

maxBytes of 100 KB and 50 KB both returned the same 111.5 KB file at VMAF 30.7, with a low verdict and an infeasible_size status. There was no smaller file to return at that codec and resolution, and asking for half as much did not move the floor.

VMAF 30.7 is unusable. The row is still the useful one: on a source like this, a tool that always returns the size you asked for has to either miss the size without telling you or destroy the picture to hit it. Check which one yours does.

What I would want from any compressor

A compressor that always compresses is easy to build and easy to trust wrongly. The behaviours I would look for are the ones where it declines: refusing to grow a file, reporting a floor it cannot pass, and saying so in a field you can branch on. None of them show up in a feature list. They show up when you run a set of cases on a file that is already good and read the verdict column.

Frequently asked questions

Why is my compressed video bigger than the original?

The original was already encoded efficiently, and the settings you re-encoded with spend more bits than it did. A higher CRF, a slower preset or a more efficient codec can help, but sometimes the right answer is to keep the original.

How do I force compress.target to re-encode anyway?

Set forceReencode: true in the params. The job then returns its best encode even when that encode is larger than the source, instead of passing the original through.

Sources

Tags #compression#vmaf#ffmpeg#api#benchmarks
All posts
Share
  1. How we benchmark FFmpeg Engineering blog
  2. Custom fonts in a video API fail silently Engineering blog
  3. Opus vs AAC vs MP3, requested vs delivered bitrate Engineering blog