Getting video dimension / resolution / width x height from ffmpeg

45,429

Solution 1

Have a look at mediainfo Handles most of the formats out there.

If you looking for a way to parse the output from ffmpeg, use the regexp \d+x\d+

Example using perl:

$ ./ffmpeg -i test020.3gp 2>&1 | perl -lane 'print $1 if /(\d+x\d+)/'
176x120

Example using python (not perfect):

$ ./ffmpeg -i /nfshome/enilfre/pub/test020.3gp 2>&1 | python -c "import sys,re;[sys.stdout.write(str(re.findall(r'(\d+x\d+)', line))) for line in sys.stdin]"

[][][][][][][][][][][][][][][][][][][]['176x120'][][][]

Python one-liners aren't as catchy as perl ones :-)

Solution 2

Use ffprobe

Example 1: With keys / variable names

ffprobe -v error -show_entries stream=width,height -of default=noprint_wrappers=1 input.mp4
width=1280
height=720

Example 2: Just width x height

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

Example 3: JSON

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

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

Example 4: JSON Compact

ffprobe -v error -select_streams v -show_entries stream=width,height -of json=compact=1 input.mkv 
{
    "programs": [

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

Example 5: XML

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

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

What the options do:

  • -v error Make a quiet output, but allow errors to be displayed. Excludes the usual generic FFmpeg output info including version, config, and input details.

  • -show_entries stream=width,height Just show the width and height stream information.

  • -of option chooses the output format (default, compact, csv, flat, ini, json, xml). See FFprobe Documentation: Writers for a description of each format and to view additional formatting options.

  • -select_streams v:0 This can be added in case your input contains multiple video streams. v:0 will select only the first video stream. Otherwise you'll get as many width and height outputs as there are video streams. -select_streams v can be used to show info from all video streams and avoid empty audio stream info in JSON and XML output.

  • See the FFprobe Documentation and FFmpeg Wiki: FFprobe Tips for more info.

Solution 3

As mentioned here, ffprobe provides a way of retrieving data about a video file. I found the following command useful ffprobe -v quiet -print_format json -show_streams input-video.xxx to see what sort of data you can checkout.

I then wrote a function that runs the above command and returns the height and width of the video file:

import subprocess
import shlex
import json

# function to find the resolution of the input video file
def findVideoResolution(pathToInputVideo):
    cmd = "ffprobe -v quiet -print_format json -show_streams"
    args = shlex.split(cmd)
    args.append(pathToInputVideo)
    # run the ffprobe process, decode stdout into utf-8 & convert to JSON
    ffprobeOutput = subprocess.check_output(args).decode('utf-8')
    ffprobeOutput = json.loads(ffprobeOutput)

    # find height and width
    height = ffprobeOutput['streams'][0]['height']
    width = ffprobeOutput['streams'][0]['width']

    return height, width

Solution 4

From Fredrik's tip above, here is how I did it using MediaInfo ( http://mediainfo.sourceforge.net/en ):

>>> p1 = subprocess.Popen(['mediainfo', '--Inform=Video;%Width%x%Height%',         
    '/Users/david/Desktop/10stest720p.mov'],stdout=PIPE)
>>> dimensions=p1.communicate()[0].strip('\n')
>>> dimensions
'1280x688'

Solution 5

In this blog post theres a rough solution in python:

import subprocess, re
pattern = re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')

def get_size(pathtovideo):
    p = subprocess.Popen(['ffmpeg', '-i', pathtovideo],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    match = pattern.search(stderr)
    if match:
        x, y = map(int, match.groups()[0:2])
    else:
        x = y = 0
    return x, y

This however assumes it's 3 digits x 3 digits (i.e. 854x480), you'll need to loop through the possible dimension lengths, such as (1280x720):

possible_patterns = [re.compile(r'Stream.*Video.*([0-9]{4,})x([0-9]{4,})'), \
            re.compile(r'Stream.*Video.*([0-9]{4,})x([0-9]{3,})'), \
re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')]

and check if match returns None on each step:

for pattern in possible_patterns:
    match = pattern.search(stderr)
    if match!=None:
        x, y = map(int, match.groups()[0:2])
        break

if match == None:
    print "COULD NOT GET VIDEO DIMENSIONS"
    x = y = 0

return '%sx%s' % (x, y)

Could be prettier, but works.

Share:
45,429

Related videos on Youtube

David542
Author by

David542

Updated on May 29, 2021

Comments

  • David542
    David542 about 3 years

    How would I get the height and width of a video from ffmpeg's information output. For example, with the following output:

    $ ffmpeg -i video.mp4
    ...
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4':
      Metadata:
        major_brand     : isom
        minor_version   : 1
        compatible_brands: isomavc1
        creation_time   : 2010-01-24 00:55:16
      Duration: 00:00:35.08, start: 0.000000, bitrate: 354 kb/s
        Stream #0.0(und): Video: h264 (High), yuv420p, 640x360 [PAR 1:1 DAR 16:9], 597 kb/s, 25 fps, 25 tbr, 25k tbn, 50 tbc
        Metadata:
          creation_time   : 2010-01-24 00:55:16
        Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 109 kb/s
        Metadata:
          creation_time   : 2010-01-24 00:55:17
    At least one output file must be specified
    

    How would I get height = 640, width= 360?

  • Geoff
    Geoff about 9 years
    This is helpful, but I think OP wanted to capture the values in python.
  • llogan
    llogan about 9 years
    @Geoff This will provide the needed values, and will be more reliable than the other method shown here. How it's used with Python is up to the user.
  • P.R.
    P.R. about 9 years
    This one fails in when I tested, because the stream info is Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj420p(pc, bt470bg/unknown/unknown), 733x446 [SAR 1:1 DAR 733:446], 7516 kb/s, 60 fps, 60 tbr, 60 tbn, 60 tbc, so the result is [][][][][][][][][][][][][]['0x47504', '733x446'][]
  • Geoff
    Geoff about 9 years
    Indeed. It helped me a lot. Thanks. Very easy to parse with re.search using the subprocess package to capture the output. Sorry for sounding negative.
  • Simon Steinberger
    Simon Steinberger almost 9 years
    -of json returns the data in JSON format, which is easier accessible in Python (avoiding regex).
  • llogan
    llogan almost 9 years
    @SimonSteinberger Edited to mention json, along with all the other available formats.
  • Agile Bean
    Agile Bean almost 6 years
    The advantage of this solution is that it returns the correct dimensions not only for mp4 but also m4v. The method by @oldo.nicho proposed wouldn't work as m4v stores the dimensions not in the first but second json array
  • Agile Bean
    Agile Bean almost 6 years
    This is great but it doesn't work for m4v which stores the dimensions in the second array. so only then, the dimensions must be retrieved by height = ffprobeOutput['streams'][1]['height'] and width = ffprobeOutput['streams'][0]['width']
  • nicbou
    nicbou over 3 years
    This is an excellent answer. If you pass the JSON output to Python, you can parse it with json.loads(cmd_output). You saved me quite a bit of trouble!
  • zui-coding
    zui-coding over 3 years
    Sometime ,the width and height value are wrong, It may be related to display_aspect_ratio, I encountered this situation. please help me
  • llogan
    llogan over 3 years
    @zui-coding You should ask a new question. Show your command and the full log, and describe how you determine the values are wrong.
  • Choy
    Choy almost 3 years
    possible to get video resolution? 4k? 2k?
  • llogan
    llogan almost 3 years
    @Choy ffprobe can't tell you if something is 4k or 2k or whatever. It will tell you the width and height of the video which you can use to determine if something is 4k. For example, if ffprobe gives you 4096x3072 then that is 4k.
  • Hashim Aziz
    Hashim Aziz over 2 years
    In the second example, what does the v after select_streams do?
  • llogan
    llogan over 2 years
    @HashimAziz It is mentioned in the answer: "-select_streams v:0 This can be added in case your input contains multiple video streams. v:0 will select only the first video stream. Otherwise you'll get as many width and height outputs as there are video streams. -select_streams v can be used to show info from all video streams and avoid empty audio stream info in JSON and XML output." So it has been added to avoid the extra, empty lines for that blank audio info that appear for some output formats.
  • Hashim Aziz
    Hashim Aziz over 2 years
    @llogan Apologies, it was late and I was skimming
  • llogan
    llogan over 2 years
    @HashimAziz I didn't even remember it was there until I was about to reply. I'm guessing 98% of readers skip the notes anyway.
  • Mark Rogers
    Mark Rogers over 2 years
    I think the answer is cool, but its usually easier to get access to ffmpeg than ffprobe because many libraries carry a copy of one but not the other.