2011-09-09 79 views
7

如何从ffmpeg的信息输出中获取视频的高度和宽度。例如,下面的输出 -从ffmpeg获取视频尺寸-i

$ 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 

如何,我会得到height = 640, width= 360?谢谢。

回答

7

看看mediainfo处理大部分格式。

如果你正在寻找一种方式来解析从ffmpeg的输出,使用正则表达式\d+x\d+

例用perl:

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

示例使用python(不完美):

$ ./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单行不如perl的那些:-)

+0

完美,非常感谢你。 – David542

+1

这个测试失败,因为流信息是流#0:0:视频:mjpeg(MJPG/0x47504A4D),yuvj420p(pc,bt470bg /未知/未知),733x446 [SAR 1:1 DAR 733: 446],7516 kb/s,60 fps,60 tbr,60 tbn,60 tbc',所以结果是[] [] [] [] [] [] [] [] [] [] [] [] [] ['0x47504','733x446'] []' –

3

从上面弗雷德里克的舌尖上口,这里是我做到了使用的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

this blog post那里有一个粗略的解决方案在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 

然而,这假定它是3个位数×3个位数(即854×480),你会通过可能的尺寸长度,如(1280×720),需要循环:

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,})')] 

,并检查是否匹配返回None每一步:

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) 

可能是更漂亮,但作品。

1

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,}×[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 
+0

或(\ d {2,} x \ d +) –

0

无需重新模块

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") 

编辑:不太好回答,因为不是所有的影片有 “PAR” 信息:(

1

要回答这个问题,最好的方法是让ffmpeg开发人员准确解释ffmpeg输出的格式应该是什么,以及我们是否可以始终假定大小位于其中的指定上下文中。在此之前,我们只能从例子中猜出通常的格式。

这是我的尝试。与这些“单线”相比,这是一个冗长的问题,但那是因为我想知道为什么它最终会失败。

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] 
29

使用ffprobe

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

什么选择呢:

  • -v error安静地输出,但允许显示错误。排除通常的FFmpeg输出信息,包括版本,配置和输入详细信息。

  • -show_entries stream=width,height只显示widthheight流信息。

  • -of default=noprint_wrappers=1这将省略通常在输出中显示的[STREAM]...[/STREAM]包装。如果您还想要省略width=height=键,请使用-of default=noprint_wrappers=1:nokey=1

  • 其他输出格式选项可满足您的需求。这些可以通过-of(又名-print_format)选项进行设置,格式为:default,compact,csv,flat,ini,json,xml。请参阅FFprobe Documentation: Writers了解每种格式的说明并查看其他选项。

  • -select_streams v:0如果您的输入包含多个视频流,则可以添加此选项。 v:0将只选择第一个视频流。否则,您将获得尽可能多的widthheight输出,因为有视频流。

  • 查看FFprobe DocumentationFFmpeg Wiki: FFprobe Tips了解更多信息。

+0

这很有帮助,但我认为OP希望捕获python中的值。 – Geoff

+0

@Geoff这将提供所需的值,并且比此处显示的其他方法更可靠。它如何与Python一起使用取决于用户。 – LordNeckbeard

+0

确实。这对我帮助很大。谢谢。使用'subprocess'软件包''re.search'很容易解析并捕获输出。抱歉,听起来不利。 – Geoff

2

如上所述,ffprobe提供了一种检索关于视频文件的数据的方法。我发现以下命令有用ffprobe -v quiet -print_format json -show_streams input-video.xxx来查看可以结帐的数据类型。

我然后写运行上面的命令,并返回视频文件的高度和宽度的函数:

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