Getting video size from ffmpeg -i

How to get the height and width of a video from ffmpeg information output. For example, with the following output -

 $ ffmpeg -i 1video.mp4 ... Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/david/Desktop/1video.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 do I get height = 640, width= 360 ? Thanks.

+7
source share
8 answers

Take a look at mediainfo Handle most formats.

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

An example of using perl:

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

An example of 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'] [] [] []

Single-line Python is not as catchy as perl :-)

+7
source

Use ffprobe :

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

What options do:

  • -v error Make a quiet conclusion, but allow the display of errors. Excludes normal general FFmpeg output information, including version, configuration, and input data.

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

  • -of default=noprint_wrappers=1 This omits the wrappers [STREAM]...[/STREAM] , which usually appear on the output. If you also want to omit the width= and height= keys, use -of default=noprint_wrappers=1:nokey=1 .

  • Other output format options are available to suit your needs. They can be set using the -of option (aka -print_format ), and the formats are: default, compact, csv, flat, ini, json, xml. See FFprobe Documentation: Writers for a description of each format and for more options.

  • -select_streams v:0 This can be added if your input contains multiple video streams. v:0 will select only the first video stream. Otherwise, you will get as many width and height outputs as there are video streams.

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

+29
source

From the tip of Fredrick above, here's 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' 
+3
source

In this blog post, this is a rude 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 that it is 3 digits x 3 digits (i.e. 854x480), you will need to skip the possible measurement lengths, for example (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 no one returns at 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) 

It may be prettier, but it works.

+3
source

As already mentioned, ffprobe provides a way to get data about a video file. I found the following command useful ffprobe -v quiet -print_format json -show_streams input-video.xxx to find out what data you can check.

Then I 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 
+2
source

BAD (\ d + x \ d +)

 $ echo 'Stream #0:0(eng): Video: mjpeg (jpeg / 0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /(\d+x\d+)/' > 0x6765706 

GOOD ([0-9] {2,} x [0-9] +)

 $ echo 'Stream #0:0(eng): Video: mjpeg (jpeg / 0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /([0-9]{2,}x[0-9]+)/' > 1280x720 
+1
source

The best way to answer this question would be the ffmpeg developer, to explain exactly what the ffmpeg output format should be, and whether we can consistently assume that the size will be in a specific context within it. Until then, we can only guess from the example which format usually is.

Here is my attempt. This is verbose compared to these β€œsingle-line” ones, but this is because I would like to know why it fails when this happens in the end.

 import subprocess def get_video_size(video_filename): """Returns width, height of video using ffprobe""" # Video duration and hence start time proc = subprocess.Popen(['ffprobe', video_filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) res = proc.communicate()[0] # Check if ffprobe failed, probably on a bad file if 'Invalid data found when processing input' in res: raise ValueError("Invalid data found by ffprobe in %s" % video_filename) # Find the video stream width_height_l = [] for line in res.split("\n"): # Skip lines that aren't stream info if not line.strip().startswith("Stream #"): continue # Check that this is a video stream comma_split = line.split(',') if " Video: " not in comma_split[0]: continue # The third group should contain the size and aspect ratio if len(comma_split) < 3: raise ValueError("malform video stream string:", line) # The third group should contain the size and aspect, separated # by spaces size_and_aspect = comma_split[2].split() if len(size_and_aspect) == 0: raise ValueError("malformed size/aspect:", comma_split[2]) size_string = size_and_aspect[0] # The size should be two numbers separated by x width_height = size_string.split('x') if len(width_height) != 2: raise ValueError("malformed size string:", size_string) # Cast to int width_height_l.append(map(int, width_height)) if len(width_height_l) > 1: print "warning: multiple video streams found, returning first" return width_height_l[0] 
+1
source

without re module

 out = error_message.split() # make a list from resulting error string out.reverse() for index, item in enumerate(out): # extract the item before item= "[PAR" if item == "[PAR": # dimension_string = out[i+1] # video_width, video_height = dimension_string.split("x") 

Edit: not a good answer, because not all videos have this information "PAR" :(

0
source

All Articles