83

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.

7 Answers 7

122

Use ffprobe

For example:

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

Output in the format:

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

Output in the format:

width=1280
height=720

Default With No Key

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

Output in the format:

1280
720

CSV

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

Output in the format:

1280,720

JSON

ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of json input.mp4

Output in the format:

{
    "programs": [

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

XML

ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of xml input.mp4

Output in the format:

<?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
    <programs>
    </programs>

    <streams>
        <stream width="1280" height="720"/>
    </streams>
</ffprobe>
11
  • Using eval is risky and not really necessary for this. stackoverflow.com/questions/17529220/… Oct 12, 2016 at 17:25
  • 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
    Mar 28, 2018 at 18:33
  • I got two result with that command { "programs": [ { "streams": [ { "width": 640, "height": 360 } ] } ], "streams": [ { "width": 640, "height": 360 } ] }
    – Salem F
    May 30, 2018 at 21:51
  • 2
    @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
    Jul 22, 2018 at 3:38
  • 1
    @ΩmegaΔ -of "csv=s=\ :p=0"
    – llogan
    Jan 28, 2020 at 21:11
10

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

Width:

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

1280

Height:

$ 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.
3
  • 2
    The 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
    Mar 14, 2018 at 21:30
  • @LordNeckbeard I agree, but this is an option for those who do not wish to ffprobe for whatever reason.
    – aalaap
    Nov 6, 2018 at 7:19
  • Also your code play the whole file if I am not mistaken
    – Natim
    Jul 30, 2019 at 14:50
3

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}"
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!

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
1
  • You also need to use STDERR. I fixed that part.
    – slhck
    Nov 18, 2014 at 14:11
1

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.

1

edit: FFPROBE solution for windows batch. Use this instead of the FFMPEG-only method, because that's parsing input meant for humans and it broke on me.

 ::Gets resolution
 for /f "tokens=*" %%g in ('"ffprobe.exe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 "input.mp4""') do (set videoRes=%%g)

 echo videoRes=%videoRes%

 ::OPTIONAL: Gets individual x and y resolutions if you want that
 for /f "tokens=1 delims=x" %%x in ("%videoRes%") do set "xRes=%%x"
 for /f "tokens=2 delims=x" %%y in ("%videoRes%") do set "yRes=%%y"

 echo xRes=%xRes%
 echo yRes=%yRes%

FFMPEG-only solution for windows batch. Don't use because it's brittle. It probably only works if you only have 1 video stream in the file, you'll have to alter it if there are more.

@echo off >nul 2>&1
setlocal enableDelayedExpansion >nul 2>&1

for /f "tokens=*" %%g in ('"ffmpeg -i input.mp4 2>&1 | findstr Video:"') do (set videoInfo=%%g)
for /f "tokens=4 delims=," %%g in ("!videoInfo!") do set "videoInfo=%%g"
for /f "tokens=1 delims=x " %%x in ("!videoInfo!") do set "xRes=%%x"
for /f "tokens=2 delims=x " %%y in ("!videoInfo!") do set "yRes=%%y"

echo xRes=!xRes!
echo yRes=!yRes!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .