79

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.

llogan
  • 57,139
  • 15
  • 118
  • 145
Vladimir Stazhilov
  • 925
  • 1
  • 8
  • 8

7 Answers7

116

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>
Alan W. Smith
  • 455
  • 1
  • 5
  • 11
llogan
  • 57,139
  • 15
  • 118
  • 145
  • 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 Oct 12 '16 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 '18 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 '18 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 '18 at 03:38
  • Could you please advise how to get simple output of the video length? Thanks – Ωmega Δ Jan 28 '20 at 12:37
  • @ΩmegaΔ See [How to get video duration in seconds?](https://superuser.com/a/945604) – llogan Jan 28 '20 at 18:07
  • @llogan - I would like to print them together (resolution and sexagesimal length) with running `ffprobe` just once. Possible? – Ωmega Δ Jan 28 '20 at 20:05
  • @ΩmegaΔ `ffprobe -v error -sexagesimal -show_entries stream=width,height:format=duration -of default=nw=1 input.mp4` – llogan Jan 28 '20 at 20:15
  • @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 Δ Jan 28 '20 at 20:27
  • 1
    @ΩmegaΔ `-of "csv=s=\ :p=0"` – llogan Jan 28 '20 at 21:11
  • @llogan - Genius! Thank you!!! – Ωmega Δ Jan 28 '20 at 21:53
9

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
  • 690
  • 10
  • 21
  • 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 '18 at 21:30
  • @LordNeckbeard I agree, but this is an option for those who do not wish to `ffprobe` for whatever reason. – aalaap Nov 06 '18 at 07:19
  • Also your code play the whole file if I am not mistaken – Natim Jul 30 '19 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 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
  • 1,461
  • 1
  • 19
  • 27
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!
Hyper
  • 11
  • 2
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
slhck
  • 223,558
  • 70
  • 607
  • 592
Andreas F
  • 333
  • 1
  • 12
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
  • 925
  • 1
  • 8
  • 8