How do I use ffmpeg to get the video resolution?

24

6

I am trying to get resolution of the video with the following command:

ffmpeg -i filename.mp4

I get a long output, but I need just the width and height for my bash script. How should I filter out those parameters? Maybe there's a better way to do this.

Vladimir Stazhilov

Posted 2014-11-17T12:21:34.940

Reputation: 375

Answers

39

Use ffprobe

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4
  1280x720

Examples of other output formatting choices

See -of option documentation for more choices and options. Also see FFprobe Tips for other examples including duration and frame rate.

Default

With no [STREAM] wrapper:

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of default=nw=1 input.mp4
  width=1280
  height=720

With no key:

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of default=nw=1:nk=1 input.mp4
  1280
  720

CSV

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 input.mp4
  1280,720

JSON

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of json input.mp4
{
    "programs": [

    ],
    "streams": [
        {
            "width": 1280,
            "height": 720
        }
    ]
}

XML

$ ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of xml input.mp4
<?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
    <programs>
    </programs>

    <streams>
        <stream width="1280" height="720"/>
    </streams>
</ffprobe>

llogan

Posted 2014-11-17T12:21:34.940

Reputation: 31 929

Using eval is risky and not really necessary for this. http://stackoverflow.com/questions/17529220/why-should-eval-be-avoided-in-bash-and-what-should-i-use-instead

– Nathaniel M. Beaver – 2016-10-12T17:25:23.330

1@bariumbitmap Thanks. eval in the answer has been eliminated for a super simple solution that I somehow missed despite staring at the documentation for years. – llogan – 2018-03-28T18:33:25.997

I got two result with that command { "programs": [ { "streams": [ { "width": 640, "height": 360 } ] } ], "streams": [ { "width": 640, "height": 360 } ] } – Salem F – 2018-05-30T21:51:12.987

1@SalemF Append | sort -nur | head -n 1. This returns the resolution with the largest width. That being said, in all cases I've ever seen, there is only one resolution, but that may be duplicated. – Cyker – 2018-07-22T03:38:13.697

Could you please advise how to get simple output of the video length? Thanks – Ωmega Δ – 2020-01-28T12:37:30.777

@ΩmegaΔ See How to get video duration in seconds?

– llogan – 2020-01-28T18:07:17.853

@llogan - I would like to print them together (resolution and sexagesimal length) with running ffprobe just once. Possible? – Ωmega Δ – 2020-01-28T20:05:34.560

@ΩmegaΔ ffprobe -v error -sexagesimal -show_entries stream=width,height:format=duration -of default=nw=1 input.mp4 – llogan – 2020-01-28T20:15:04.300

@llogan - I used ffprobe -v error -select_streams v:0 -show_entries stream=width,height,duration -of csv=s=x:p=0 -sexagesimal input.mp4, but I would like to change separator s=x to a standard space character. I cannot find documentation how to use space character in csv parameter. Please advise. Thanks – Ωmega Δ – 2020-01-28T20:27:40.690

@ΩmegaΔ -of "csv=s=\ :p=0" – llogan – 2020-01-28T21:11:34.053

@llogan - Genius! Thank you!!! – Ωmega Δ – 2020-01-28T21:53:47.270

4

The following commands rely purely on ffmpeg (and grep and cut) to get you the height or width as required:

Height:

$ ffmpeg -i video.mp4 2>&1 | grep Video: | grep -Po '\d{3,5}x\d{3,5}' | cut -d'x' -f1

1280

Width:

$ ffmpeg -i video.mp4 2>&1 | grep Video: | grep -Po '\d{3,5}x\d{3,5}' | cut -d'x' -f2

720

The difference between the two is just the -f parameter to cut.

If you prefer the full resolution string, you don't need cut:

$ ffmpeg -i video.mp4 2>&1 | grep Video: | grep -Po '\d{3,5}x\d{3,5}'

1280x720

Here's what we're doing with these commands:

  1. Running ffmpeg -i to get the file info.
  2. Extracting the line which just contains Video: information.
  3. Extracting just a string that looks like digitsxdigits which are between 3 and 5 characters.
  4. For the first two, cutting out the text before or after the x.

aalaap

Posted 2014-11-17T12:21:34.940

Reputation: 592

1The output from ffmpeg is only meant for human eyes, and not meant to be parsed by scripts or other tools. The output is not standardized and so it is not guaranteed to be the same format for all files, so it is a fragile use case. Use ffprobe instead. Lots of examples here in this thread. – llogan – 2018-03-14T21:30:25.507

@LordNeckbeard I agree, but this is an option for those who do not wish to ffprobe for whatever reason. – aalaap – 2018-11-06T07:19:12.997

Also your code play the whole file if I am not mistaken – Natim – 2019-07-30T14:50:42.833

2

The output of ffprobe looks like this:

streams_stream_0_width=1280
streams_stream_0_height=720

Technically, you can use eval to assign these to bash variables, but this is not necessary and can be unsafe; see here for more:

https://stackoverflow.com/questions/17529220/why-should-eval-be-avoided-in-bash-and-what-should-i-use-instead

Instead, since you are using bash, take advantage of its built-in arrays and string manipulation:

filepath="filename.mp4"
width_prefix='streams_stream_0_width='
height_prefix='streams_stream_0_height='
declare -a dimensions
while read -r line
do
    dimensions+=( "${line}" )
done < <( ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=width,height "${filepath}" )
width_with_prefix=${dimensions[0]}
height_with_prefix=${dimensions[1]}
width=${width_with_prefix#${width_prefix}}
height=${height_with_prefix#${height_prefix}}
printf "%s\t%sx%s\n" "${filepath}" "${width}" "${height}"

Nathaniel M. Beaver

Posted 2014-11-17T12:21:34.940

Reputation: 312

1

Use grep to select only those lines you are looking for. Redirect the output from STDERR to STDOUT, since ffmpeg will output all info there.

ffmpeg -i filename.mp4 2>&1 | grep <keyword>

Edit: A full working example using perl:

$ ffmpeg -i MVI_7372.AVI 2>&1 | grep Video | perl -wle 'while(<>){ $_ =~ /.*?(\d+x\d+).*/; print $1 }'
640x480

Andreas F

Posted 2014-11-17T12:21:34.940

Reputation: 323

You also need to use STDERR. I fixed that part. – slhck – 2014-11-18T14:11:19.397

1

I finally found the answer:

I used this package called Media info

And then I commanded:

mediainfo mediainfo --Inform="Video;%Width%" midhand.mp4

To view the list of params:

mediainfo --Info-Parameters

Best tool to extract video metadata!

Vladimir Stazhilov

Posted 2014-11-17T12:21:34.940

Reputation: 375

0

I know the question is about bash but, just in case someone ends here looking for a solution for a Windows batch, as myself before I found it out.

for /f "delims=" %%a in ('ffprobe -hide_banner -show_streams filename.mp4 2^>nul ^| findstr "^width= ^height="') do set "myvideo_%%a"

No console messages, and you end with the nice environment variables myvideo_width and myvideo_height. You can check it with:

C:\>set myvideo_
myvideo_height=720
myvideo_width=1280

If the resolution of your video is 1280x720, of course.

cdlvcdlv

Posted 2014-11-17T12:21:34.940

Reputation: 703