Common ffprobe commands compared

Compare 25 ffprobe command shapes on median run time and billed cost, measured across 213 real probe jobs run on production infrastructure.

Share

Short version

ffprobe reads a media file’s metadata and prints it. The flags decide which sections you get and in what shape, and almost nothing else.

We pulled 213 ffprobe jobs out of Rendobar’s job history. They ran 25 distinct command shapes, 200 completed and 13 did not. Every shape’s median run time landed between 95 ms and 402 ms, which is the useful headline: the flags you choose change what you see, not what it costs you in time.

The variation that matters is inside a single shape rather than between shapes. The same command against different files ran anywhere from 94 ms to 4,367 ms.

The commands, with what they measured

Medians below are across the jobs that used that exact shape, so the counts are honest and some are small. Read them as an order of magnitude and nothing finer.

Command shapeCompleted jobsMedian
just a URL, no flags107171 ms
-show_format -show_streams34282 ms
ffprobe <url>10294 ms
-v quiet -print_format json -show_format -show_streams8251 ms
-show_streams5113 ms
-v error -show_entries format=duration:stream=index -of json497 ms
-v quiet -print_format json -show_format3302 ms
-print_format csv -show_format3101 ms
-show_frames -read_intervals %+#53120 ms
-select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate -print_format json3101 ms

The gap between the fastest and slowest median here is under 4x, on samples as small as three jobs, against different files, over a network. That is not enough to call one shape faster than another and we are not going to. What it does establish is that no shape in this set is expensive. There is no flag here that turns a 100 ms operation into a 10 second one.

-count_frames would be the exception, because it decodes packets rather than reading a header, but it did not appear in this archive often enough to publish a number for.

The prefix is optional and so is most of the rest

116 of 213 jobs, half the corpus, passed nothing but a URL. No ffprobe, no flags.

That works because sensible defaults fill in for flags you did not pass. JSON output, format, streams and chapters all get added when absent, and anything you did specify is left exactly as written. So a command copied out of a Stack Overflow answer runs the way it does on your laptop, and a bare URL still returns something useful.

The practical effect is that these three are equivalent for most purposes:

Terminal window
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
ffprobe input.mp4
input.mp4

Picking the right shape for the job

Looking at a file by hand. Use the full JSON. You want everything, and you are reading it rather than parsing it.

Terminal window
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

Pulling one field in a script. Use -show_entries with -of csv=p=0. Anything else makes you parse output you did not want.

Terminal window
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4

Deciding what to do next. Select the stream, then ask for the fields the decision depends on. This is the shape that appeared before compose and transcode jobs in the archive.

Terminal window
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,r_frame_rate \
-print_format json input.mp4

Checking the start of a file without reading all of it. -read_intervals %+#5 stops after five packets, which is enough to see whether the first frames decode at all.

Terminal window
ffprobe -show_frames -read_intervals %+#5 input.mp4

The output shapes

-print_format (or -of, they are the same flag) decides the writer.

json is the one to use in code. It nests cleanly, it survives commas in tag values, and every language reads it. csv is the one to use in a shell when you want a single value, especially with p=0 to drop the section prefix. flat and ini produce assignable key-value lines, which suit eval in a shell script if you trust the input. xml exists.

The trap in csv is that it does not quote fields, so a title tag containing a comma splits into two columns. If the value could contain arbitrary text, use json and parse it properly.

Cost, and why it is a flat number

Every probe run since 2026-07-20 billed exactly $0.0010, across 169 consecutive jobs with no variance at all. Before that date the amounts moved with execution time and ranged down to $0.000091.

A flat floor is the right shape for this operation. The work is dominated by fetching enough of the file to read a header, and the difference between a 40 KB JPEG and a six-minute MP3 is not worth metering. It also makes the number predictable, which matters when a probe runs before every job in a pipeline rather than occasionally.

For comparison, the FFmpeg jobs in the same archive have a median of $0.0025 and a 90th percentile of $0.0042 over the last 425 runs. Probing costs roughly 40% of what a median encode costs, and it is the step that tells you whether the encode is worth running at all.

Running it over HTTP

Every measurement on this page came from a job submitted to Rendobar’s FFmpeg API, which takes the ffprobe command as a string.

job.ts
import { createClient } from "@rendobar/sdk";
const rb = createClient({ apiKey: process.env.RENDOBAR_API_KEY });
const job = await rb.jobs.run({
type: "ffprobe",
params: {
command:
"ffprobe -v quiet -print_format json -show_format -show_streams https://cdn.rendobar.com/assets/examples/sample.mp4",
},
});
// Raw ffprobe report, exactly as the binary produced it.
console.log(job.output.data.format.format_name); // "mov,mp4,m4a,3gp,3g2,mj2"
// Plus a normalised summary: codec, resolution, fps, rotation, HDR, audio layout.
console.log(job.output.data.summary.video); // { codec: "h264", width: 1280, ... }

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": "ffprobe",
"params": { "command": "ffprobe -v quiet -print_format json -show_format -show_streams https://cdn.rendobar.com/assets/examples/sample.mp4" }
}'

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

The response carries the raw ffprobe report and a normalised summary alongside it, with codec, resolution, duration, fps, rotation, HDR signalling and audio layout already resolved. That summary exists because reading those fields correctly out of raw ffprobe output is harder than it looks.

Where this stops

Every number here is an observation from production traffic, not a controlled benchmark. The jobs ran on different days against different files over a network we do not control, so the timings carry all of that variance and none of it was held constant. Several shapes have a sample of one to three jobs and their medians should be read as “roughly this order” rather than as measurements.

The 13 jobs that did not complete are not analysed here. The list endpoint does not carry an error code, so classifying them needs a separate pass.

Nothing here covers -count_frames at scale, MKV or WebM inputs, HLS or DASH manifests, or files large enough for header placement to dominate. Those are the cases where a probe stops being a fixed 200 ms operation.

Two posts go deeper on specific traps. How to get video duration with ffprobe covers why the container and the video stream disagree by up to 493 ms. ffprobe metadata gotchas covers rotation, fake image durations, missing channel layouts and cover art posing as video.

Frequently asked questions

What is the most useful ffprobe command?

ffprobe -v quiet -print_format json -show_format -show_streams input.mp4 gives you the container, every stream, and all their properties as parseable JSON. It was the fourth most common shape in our archive and its median run was 251 ms.

How do I make ffprobe output JSON?

Add -print_format json, or the equivalent -of json. Pair it with -v quiet so the version banner does not land on stderr and confuse anything reading both streams.

How do I get just one field from ffprobe?

Use -show_entries to pick the section and field, and -of csv=p=0 to strip the section label. For example -show_entries format=duration -of csv=p=0 prints the duration and nothing else.

Is ffprobe slow on large files?

Reading metadata is not, because it reads a header rather than the whole file. Counting frames is, because -count_frames decodes packets. In our sample the median probe was 171 ms and the slowest was 4,367 ms, and the slow ones tracked how much had to be pulled over the network before the header was readable.

Can I run ffprobe without installing FFmpeg?

Yes. Rendobar's FFmpeg API accepts a raw ffprobe command over HTTP and returns both the raw report and a normalised summary. The 213 probe jobs measured here all ran that way.

Sources

Tags #ffprobe#ffmpeg#video-metadata#media#reference
All posts
Share
  1. How to compress video to a target size Guides for the video API
  2. FFmpeg API pricing compared Guides for the video API
  3. How to burn subtitles into a video Guides for the video API